Eamonn
Eamonn

Reputation: 187

Cast to multiple inheritance

I would like to know if it is possible to cast an object to multiple classes that it inherits from without knowing its initial type. For example, suppose I have the following structs:

struct A {
    int a;
};

struct B {
    int b;
};

struct C {
    int c;
};

struct D {
    int d;
};

struct Z : A, B, C, D {};

And I add instances of Z to a vector.

vector<A *> v;
Z *zed = new Z();
v.push_back(zed);

Now suppose that I know that the first element in the vector inherits from A and B and I would like to cast it to A and B.

struct Tmp : A, B {};
Tmp *tmp = static_cast<Tmp *>(v[0]);
tmp->b = 6;
cout << zed->b << endl;

However, doing this causes issues. Mainly if Z was instead defined as struct Z : A, C, D, B {}; then cout << zed->b << endl; would print 0 and not 6. How would you get around this?

I understand that doing this is potentially unsafe and probably poor design, however, i'm still interested in knowing if it's possible.

Upvotes: 0

Views: 102

Answers (2)

Potatoswatter
Potatoswatter

Reputation: 137810

You can use dynamic_cast to go "across" the inheritance hierarchy. But there needs to be at least one virtual function in the "from" type, and you can't cast from a virtual or multiply-inherited base.

struct A {
    int a;
    virtual ~A() {}
};

struct Z : A, B, C, D {};
vector<A *> v;
Z *zed = new Z();
v.push_back(zed);

B *tmp = dynamic_cast<B *>(v[0]);

This uses runtime type inspection and yields nullptr if v[0] wasn't derived from B after all.

As for struct Tmp, according to the language it's not related to Z at all despite having common bases. What if Tmp also declared its own members? If you want access to the B and C subobjects regardless of how they were inherited, get references using two separate dynamic_cast operations.

Upvotes: 1

Shoe
Shoe

Reputation: 76240

You seem to be using A and B more than once there (both to cast and to create the Tmp struct. I'd suggest you to give an useful name to struct X : A, B {...} and define Z as: struct Z : X, C, D {}.

Then the cast becomes:

X* tmp = static_cast<X*>(v[0]);
tmp->b = 6;
std::cout << zed->b << std::endl;

Upvotes: 0

Related Questions