C++ inheritance and dynamic_cast
Published by packi on
Updated by packi on

Looking at at the following lines of C++ code:

#include <iostream>

using namespace std;

class A {
public:
  A() {};
  virtual ~A() {};
};

class B : public A {
};

class C : public A {
};

class F {
};

class D : public C,F {
};

For the C++ impaired, it defines a superclass A that has two descendants B and C. C itself has another descendant D. D has another superclass F.

If you’ve got an instance inst that’s a derivative of A you can use dynamic_cast<X*>(inst) to determine if inst is an instance of X.

I wrote a test function to determine if that’s really the case:

void test( A* _c ) {
  if( dynamic_cast<B*>(_c) ) {
    cout < "is B" < endl;
  }
  if( dynamic_cast<C*>(_c) ) {
    cout < "is C" < endl;
  }
  if( dynamic_cast<F*>(_c) ) {
    cout < "is F" < endl;
  }
}

int main() {
  cout < "creating B" < endl;
  test( new B() );
  cout < "creating C" < endl;
  test( new C() );
  cout < "creating D" < endl;
  test( new D() );
  return 0;
}

After compiling the file with g++ test.cpp and running the resulting executable I’ve got a somehow unexpected result:

patrick@pentagon ~/test $ ./a.out
creating B
is B
creating C
is C
creating D
is C
patrick@pentagon ~/test $

It is apparently a common mistake to read:

[…]
class D : public C,F {
[…]

as:

[…]
class D : public C,  public F {
[…]

when it really means:

[…]
class D : public C,  private F {
[…]

Defining the inheritance of F as public finally yielded the expected result:

patrick@pentagon ~/test $ ./a.out
creating B
is B
creating C
is C
creating D
is C
is F
patrick@pentagon ~/test $

You can download the full source for this test here.