How does multiple inheritance work internally?


R

responsible

Hi,
Please have a look at this very small piece of code...

class Base1{
public:
Base1():x(5){}
int x;
};

class Base2{
public:
Base2():y(7){}
int y;
};

class Base3{
public:
Base3():z(9){}
int z;
};

class Derived:public Base1, public Base2,public Base3{
public:
Derived():w(12){}
int w;
};

int main(void)
{
Derived* p_d = new Derived;
Base1* p_b1 = dynamic_cast<Base1*> (p_d);
Base2* p_b2 = dynamic_cast<Base2*> (p_d);
Base3* p_b3 = dynamic_cast<Base3*> (p_d);
Derived* p_d2 = static_cast<Derived*> (p_b2);
delete p_d;
return 0;
}

The code just has 3 base classes, and one class that derives from all
three of them.
Now, when I cast from Derived to any of the bases, I understand that
the pointer value may change because otherwise the new pointer will
not be able to figure out where the virtual table entry is, right?

My question, however, is, how does performing the static cast from
Base2* to Derived* "know" that it should change the address back? The
code surprisingly works fine (when you cast a Base2* to a Derived* it
automatically decrements the pointer by 4 bytes.)
Is this behavior part of the C++ language? I was curious about how it
works inside.

Thank you very much in advance
 
Ad

Advertisements

A

amparikh

Hi,
Please have a look at this very small piece of code...

class Base1{
public:
Base1():x(5){}
int x;

};

class Base2{
public:
Base2():y(7){}
int y;

};

class Base3{
public:
Base3():z(9){}
int z;

};

class Derived:public Base1, public Base2,public Base3{
public:
Derived():w(12){}
int w;

};

int main(void)
{
Derived* p_d = new Derived;
Base1* p_b1 = dynamic_cast<Base1*> (p_d);
Base2* p_b2 = dynamic_cast<Base2*> (p_d);
Base3* p_b3 = dynamic_cast<Base3*> (p_d);
Derived* p_d2 = static_cast<Derived*> (p_b2);
delete p_d;
return 0;

}

The code just has 3 base classes, and one class that derives from all
three of them.
Now, when I cast from Derived to any of the bases, I understand that
the pointer value may change because otherwise the new pointer will
not be able to figure out where the virtual table entry is, right?

My question, however, is, how does performing the static cast from
Base2* to Derived* "know" that it should change the address back? The
code surprisingly works fine (when you cast a Base2* to a Derived* it
automatically decrements the pointer by 4 bytes.)
Is this behavior part of the C++ language? I was curious about how it
works inside.

Thank you very much in advance


Here is a good article that you might find useful.

http://www.ddj.com/dept/cpp/184402074
 
R

Rolf Magnus

responsible said:
Hi,
Please have a look at this very small piece of code...

class Base1{
public:
Base1():x(5){}
int x;
};

class Base2{
public:
Base2():y(7){}
int y;
};

class Base3{
public:
Base3():z(9){}
int z;
};

class Derived:public Base1, public Base2,public Base3{
public:
Derived():w(12){}
int w;
};

int main(void)
{
Derived* p_d = new Derived;
Base1* p_b1 = dynamic_cast<Base1*> (p_d);
Base2* p_b2 = dynamic_cast<Base2*> (p_d);
Base3* p_b3 = dynamic_cast<Base3*> (p_d);

There is no need to cast from derived class to a base class.
Derived* p_d2 = static_cast<Derived*> (p_b2);
delete p_d;
return 0;
}

The code just has 3 base classes, and one class that derives from all
three of them.
Now, when I cast from Derived to any of the bases, I understand that
the pointer value may change because otherwise the new pointer will
not be able to figure out where the virtual table entry is, right?

Maybe. It's implementation dependant.
My question, however, is, how does performing the static cast from
Base2* to Derived* "know" that it should change the address back?

Because it knows where the Base2 part is within a Derived, since it has
definitions of both classes.
The code surprisingly works fine (when you cast a Base2* to a Derived* it
automatically decrements the pointer by 4 bytes.)
Is this behavior part of the C++ language?

If by "this behavior", you mean that a static_cast from pointer to base to
pointer to derived works, yes.
 
Ad

Advertisements

J

Juha Nieminen

responsible said:
My question, however, is, how does performing the static cast from
Base2* to Derived* "know" that it should change the address back?

Simple: The compiler sees the definition of Base2 and the one of
Derived, and it sees that Derived is (multiple-)inherited from Base2.
Thus it's rather trivial for it to make the proper conversion when
casting. (Of course since you are using a static_cast the compiler
doesn't perform any sanity checks and simply trusts you on that you
know what you are doing and that there really is an object of type
Derived behind the pointer. If there isn't you probably get a crash
or other misbehavior.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top