views:

108

answers:

6

I would like to check the type of a superclass A against the type of a subclass B (with a method inside the superclass A, so that B will inherit it).

Here's what I thought did the trick (that is, the use of forward declaration):

#include <iostream>
#include <typeinfo>

using namespace std;

class B;

class A {
  public:
    int i_;
    void Check () {
      if (typeid (*this) == typeid (B))
        cout << "True: Same type as B." << endl;
      else
        cout << "False: Not the same type as B." << endl;
    }
};

class B : public A {
  public:
    double d_;
};


int main () {

  A a;
  B b;

  a.Check (); // should be false
  b.Check (); // should be true

  return 0;
}

However this code does not compile. The error I get is:

main.cc: In member function ‘void A::Check()’:
main.cc:12: error: invalid use of incomplete type ‘struct B’
main.cc:6: error: forward declaration of ‘struct B’

How could I solve this problem?

A: 

One way would be to pull the definition of Check out of the class definition, so that B is defined when the compiler gets to the function definition.

class A {
    //...
    void Check();
    //...
};
class B { /* ... */ };

void A::Check() {
    //...
}
CAdaker
+1  A: 

Just move the definition of Check() out of the body of A:

#include <iostream>
#include <typeinfo>

using namespace std;

class B;

class A {
  public:
    int i_;
    void Check ();
};

class B : public A {
  public:
    double d_;
};

void A::Check () {
  if (typeid (*this) == typeid (B))
    cout << "True: Same type as B." << endl;
  else
    cout << "False: Not the same type as B." << endl;
}

int main () {

  A a;
  B b;

  a.Check (); // should be false
  b.Check (); // should be true

  return 0;
}
jon hanson
Thank for the quick answer! What you suggested actually worked. However I preferred rewriting everything in terms of virtual functions.
Jir
A: 

Move your definition of the Check below your declaration of class B.

Jesse
A: 

Just move the function body after the declaration of B.

#include <iostream>
#include <typeinfo>

struct A
{
 int i_;
 void Check();
};

struct B :  A
{
 double d_;
};

void A::Check()
{
 using namespace std;
 if (typeid (*this) == typeid (B))
 {
  cout << "True: Same type as B." << endl;
 }
 else
 {
  cout << "False: Not the same type as B." << endl;
 }
}

int main()
{
 A a;
 B b;

 a.Check(); // should be false
 b.Check(); // should be true

 return 0;
}
DrPizza
+3  A: 

I think that the problem you are trying to solve is much better handled by a virtual method:

class A
{
    public:
        virtual bool Check() { return false; };
}


class B : public A
{
    public:
        // override A::Check()
        virtual bool Check() { return true; };
}

Methods in the base class A should not need to know whether the object is "really" an A or a B. That's a violation of basic object-oriented design principles. If the behavior needs to change when the object is a B, then that behavior should be defined in B and handled by virtual method calls.

JSBangs
It did not occur to me that I was violating basic OOP principles. Not to mention that what I was trying to do did not work.As you suggested, I rewrote everything using virtual functions.Thanks!
Jir
A: 


Hi, even if you put the definition of A::Check outside the class the result won't be what you expect. This is because the B object this convert to an A object in the method so this points on a A object thus the typeids are always different. To solve this declare the method virtual.

However, I still don't understand why you want to perform such a test O_o ?? And as CAdaker said this is not good practice

Arnaud
I'd like to do that in order to trigger different methods, based on the type of class. if b.Check() then b.method_in_the_subclass(); else b.method_in_the_superclass(); But thanks to all your hints I see this hardly can be considered good practice.
Jir