C++中的多重继承有两种:一种是多层次的继承,另外就是多基类单层次的继承。这里介绍下多基类继承中基类和派生类在内存布局上的关系。先看下面的一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <iomanip>
//~ #include <sqlite.h>
//~ #include <mysql/mysql.h>
using namespace std;
 
class B1
{
    public:
        void f1(){cout<<"B1::f1()"<<endl;}
        virtual void v1(){cout<<"B1::v1()"<<endl;}
        int x;
};
 
class B2
{
    public:
        void f2(){cout<<"B2::f2()"<<endl;}
        virtual void v2(){cout<<"B2::v2()"<<endl;}
        int y;
};
 
class B3
{
    public:
        void f3(){cout<<"B3::f3()"<<endl;}
        virtual void v3(){cout<<"B3::v3()"<<endl;}
        int z;
};
 
class D:public B1, public B2, public B3
{
    public:
        void f1(){cout<<"D::f1()"<<endl;}
        virtual void v1(){cout<<"D::v1()"<<endl;}
        virtual void d(){cout<<"D::d()"<<endl;}
        int n;
};
 
int
main ()
{
    D d;
    D* pd = &d;
    B1 * pb1 = &d;
    B2 * pb2 = &d;
    B3 * pb3 = &d;
    cout<<pd<<endl;
    cout<<pb1<<endl;
    cout<<pb2<<endl;
    cout<<pb3<<endl;
    return 0;
}

程序中输出了派生类对象d的地址,以及将其赋给相应基类指针后的地址,输出结果:

0xbfbe40e8
0xbfbe40e8
0xbfbe40f0
0xbfbe40f8

可见,将d转换成第一个基类B1时,地址是不变的,而转化到其他基类时,地址会发生变化。对象的d的内存布局可以用下图来表示:

class D

class D


这里面有三张函数表,分别对应d的三个基类。事实上,d的虚函数d()的地址保存在了基类B1对应的虚函数表内。从多重继承的内存布局,我们可以看到子类新加入的虚函数被加到了第一个基类的虚函数表,所以当dynamic_cast的时候,子类和第一个基类的地址相同,不需要移动指针,但是当dynamic_cast到其他的父类的时候,需要做相应的指针的移动。

Tags: ,.
你好!除了代码,此处没有多少原创之物,皆为本人搜集、整理、总结之记录与心得,欢迎转载分享!转载时请尽量注明出处,将不胜感激。祝你健康、快乐!
Home

Be the first to comment on this entry.

Name(required)
Mail (required),(will not be published)

RFC: Request For Comments. Orz..

Website(recommended)