我是靠谱客的博主 无奈小懒猪,这篇文章主要介绍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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
class B { public: virtual void func_1()//虚函数 { cout << "B ::func_1()n"; } virtual void func_2()//虚函数 { cout << "B ::func_2()n"; } //protected: int _b; }; class C { public: virtual void func_1()//虚函数 { cout << "C ::func_1()n"; } virtual void func_3()//虚函数 { cout << "C ::func_3()n"; } //protected: int _c; }; class D :public B ,public C { public: virtual void func_1()//重写了父类中的虚函数 { cout << "D ::func_1()n"; } virtual void func_4()//Derive 类自己的虚函数 { cout << "D ::func_4()n"; } void func_5()//普通成员函数 { cout << "D ::func_5()n"; } //protected: int _d; }; typedef void(*VFUNC)(void); void PrintVTable(int *table,const string &str) { int i = 0; cout << str << endl; printf("table :0x%pn", table);//打印虚表指针 for (i = 0; table[i] != NULL; ++i) { printf("table[%d]:0x%p->", i, table[i]);//将虚表中的每一个虚函数地址打印出来 VFUNC f = (VFUNC)table[i];//将虚函数的地址转换为函数指针 f();//调用虚函数 } } int main() { D d1; d1._b = 1; d1._c = 2; d1._d = 3; PrintVTable((int *)(*((int *)(&d1))),"第一张虚表"); PrintVTable((int *)(*((int *)((char *)&d1+sizeof(B)))),"第二张虚表"); system("pause"); return 0; }

 

 

因为D继承了两个父类,所以D类中是有两张虚表,而且D对象独有的虚函数也放在第一张虚表中,这里因为D对象先继承了B对象,所以从对象模型来看,B对象在D对象的上面部分,并且B的虚表中还要存放D对象独有的虚函数,当D对func_1()进行了重写,B和C虚表中的func_1()都会被覆盖。

 

二、多继承中菱形继承

复制代码
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
class A { public: virtual void func_1()//虚函数 { cout << "A ::func_1()n"; } virtual void func_2()//独有的虚函数 { cout << "A ::func_2()n"; } //protected: int _a; }; class B :public A { public: virtual void func_1()//虚函数 { cout << "B ::func_1()n"; } virtual void func_3()//虚函数 { cout << "B ::func_3()n"; } virtual void func_4()//虚函数 { cout << "B ::func_4()n"; } //protected: int _b; }; class C :public A { public: virtual void func_1()//虚函数 { cout << "C ::func_1()n"; } virtual void func_5()//虚函数 { cout << "C ::func_5()n"; } virtual void func_6()//虚函数 { cout << "C ::func_6()n"; } //protected: int _c; }; class D :public B ,public C { public: virtual void func_1()//重写了B和C的虚函数 { cout << "D ::func_1()n"; } virtual void func_3()//重写了B的虚函数 { cout << "D ::func_3()n"; } virtual void func_5()//重写了C的虚函数 { cout << "D ::func_5()n"; } virtual void func_7()//独有的虚函数 { cout << "D ::func_7()n"; } //protected: int _d; }; typedef void(*VFUNC)(void); void PrintVTable(int *table,const string &str) { int i = 0; cout << str << endl; printf("table :0x%pn", table);//打印虚表指针 for (i = 0; table[i] != NULL; ++i) { printf("table[%d]:0x%p->", i, table[i]); //将虚表中的每一个虚函数地址打印出来 VFUNC f = (VFUNC)table[i]; //将虚函数的地址转换为函数指针 f();//调用虚函数 } } int main() { D d1; d1.B::_a = 1; d1.C::_a = 2; d1._b = 3; d1._c = 4; d1._d = 5; PrintVTable((int *)(*((int *)(&d1))),"第一张虚表"); PrintVTable((int *)(*((int *)((char *)&d1+sizeof(B)))),"第二张表"); system("pause"); return 0; }

因为是菱形继承,这里的B和C对象中都会分别有一个A对象,当然D中自己的虚函数也是放在第一个继承的父类的虚表中的,这里就是放在B对象中的A对象中的虚表中。

如果已经忘了菱形继承的请戳:点击打开链接

三、菱形虚拟继承

复制代码
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
class A { public: virtual void func_1()//虚函数 { cout << "A ::func_1()n"; } virtual void func_2()//独有的虚函数 { cout << "A ::func_2()n"; } //protected: int _a; }; class B :virtual public A { public: virtual void func_1()//虚函数 { cout << "B ::func_1()n"; } virtual void func_3()//虚函数 { cout << "B ::func_3()n"; } virtual void func_4()//虚函数 { cout << "B ::func_4()n"; } //protected: int _b; }; class C :virtual public A { public: virtual void func_1()//虚函数 { cout << "C ::func_1()n"; } virtual void func_5()//虚函数 { cout << "C ::func_5()n"; } virtual void func_6()//虚函数 { cout << "C ::func_6()n"; } //protected: int _c; }; class D :public B, public C { public: virtual void func_1()//重写了B和C的虚函数 { cout << "D ::func_1()n"; } virtual void func_3()//重写了B的虚函数 { cout << "D ::func_3()n"; } virtual void func_5()//重写了C的虚函数 { cout << "D ::func_5()n"; } virtual void func_7()//独有的虚函数 { cout << "D ::func_7()n"; } //protected: int _d; }; typedef void(*VFUNC)(void); void PrintVTable(int *table, const string &str) { int i = 0; cout << str << endl; printf("table :0x%pn", table);//打印虚表指针 for (i = 0; table[i] != NULL; ++i) { printf("table[%d]:0x%p->", i, table[i]);//将虚表中的每一个虚函数地址打印出来 VFUNC f = (VFUNC)table[i];//将虚函数的地址转换为函数指针 f();//调用虚函数 } } int main() { D d1; d1._a = 1; d1._b = 2; d1._c = 3; d1._d = 4; PrintVTable((int *)(*((int *)(&d1))), "第一张虚表"); PrintVTable((int *)(*((int *)((char *)&d1 + sizeof(B)-sizeof(A)))), "第二张虚表"); PrintVTable((int *)(*((int *)((char *)&d1 + sizeof(B)-sizeof(A)+sizeof(C) - sizeof(A)+sizeof(D)-sizeof(B)-sizeof(C)+sizeof(A)))), "第三张虚表"); system("pause"); return 0; }

 


从上面的模型来看,D类中有三张虚表,一张是A的,里面放的是B和C继承了A了虚函数,一张是放B自己的虚函数和D中独有的虚函数(因为D是先继承了B),一张是放C自己的虚函数。

当然如果B没有自己的虚函数,并且D类也没有自己独有的虚函数,那么这里就不会为B开辟块空间放B的虚函数表,同理,如果C类中没有自己独有的虚函数,那么也就不会为C开辟一块空间放C的虚函数表。

最后

以上就是无奈小懒猪最近收集整理的关于C++对象模型(中)多继承多继承体系下的对象模型的全部内容,更多相关C++对象模型(中)多继承多继承体系下内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(73)

评论列表共有 0 条评论

立即
投稿
返回
顶部