1. 题目
#include<iostream>using namespace std;class S {};class A:S { virtual void fun() { ; }};class B:A { virtual void fun() { ; }};class C:B { virtual void fun() { ; }};class M { virtual void fun() {}};class N { virtual void fun() {}};class P:M,N { virtual void fun() {}};//------------------------------class T_S {};class T_A:virtual T_S { virtual void fun() { ; }};class T_B:virtual T_A { virtual void fun() { ; }};class T_C:virtual T_B { virtual void fun() { ; }};class T_M { virtual void fun() {}};class T_N { virtual void fun() {}};class T_P:virtual T_M,T_N { virtual void fun() {}};int main() { // ---------------------------- // 单继承 cout << sizeof(S) << endl; // 1, 空类 cout << sizeof(A) << endl; // 4, 一个虚函数指针 cout << sizeof(B) << endl; // 4, 一个虚函数指针 cout << sizeof(C) << endl; // 4, 一个虚函数指针 //------------------------------ // 多继承 cout << sizeof(M) << endl; // 4, 一个虚函数指针 cout << sizeof(N) << endl; // 4, 一个虚函数指针 cout << sizeof(P) << endl; // 8, 两个虚函数指针,多继承 //------------------------------ // 单继承 cout << sizeof(T_S) << endl; // 1, 空类 cout << sizeof(T_A) << endl; // 4, 一个虚函数指针 cout << sizeof(T_B) << endl; // 4, 一个虚函数指针 cout << sizeof(T_C) << endl; // 4, 一个虚函数指针 //------------------------------ // 多继承 cout << sizeof(T_M) << endl; // 4, 一个虚函数指针 cout << sizeof(T_N) << endl; // 4, 一个虚函数指针 cout << sizeof(T_P) << endl; // 8, 两个虚函数指针,多继承 //------------------------------ system("PAUSE"); return 0;}
2. 分析
S是空类,大小默认是1。
A继承自S,S为空,A本身有虚函数,因此A需要有一个虚指针,因此A大小为4。
B继承自A,A大小为4有一个虚指针,B沿用A的虚指针,因此B大小为4。
C继承自B,B大小为有一个虚指针(实际上是沿用了A的虚指针),因此C沿用B的虚指针,因此C大小为4。
实际上,一个类对应一个虚表,上面的虚指针沿用是针对类来说的,上面A,B,C三个类分别有一个虚指针,当然B和C的都是继承来的。
对于虚拟继承,即TS,TA,TB,TC并没有改变虚指针的问题,也没有像一下bolg文章里面说的,虚继承相当与增加虚表指针和父类的所有东西。
值得注意的是:A类如果有虚指针,其子类无论有没有虚函数,都会继承上面的虚指针,而且子类即使有虚函数也不会再去增加一个自己的虚指针,每个类最多有一个虚指针,对应最多有一个虚表。
M有一个虚指针,N有一个虚指针,P继承了M和N,有两个虚指针,因此P的大小为8。
PS:以上针对32机器,指针长度为4字节。
3. 补充一个和前面的题目有微小区别
#include <iostream>using namespace std;class S {};class A:public S {public: virtual void func() { cout << "A" << endl; }};class B:public A {public: virtual void func() { cout << "B" << endl; }};class C:public A {public: void func() { cout << "C" << endl; }};class D:public C {};int main() { A* pa = new A; A* pb = new B; A* pc = new C; pa->func(); // A pb->func(); // B pc->func(); // C cout << sizeof(S) << endl; // 1 cout << sizeof(A) << endl; // 4 cout << sizeof(B) << endl; // 4 cout << sizeof(C) << endl; // 4 cout << sizeof(D) << endl; // 4 system("PAUSE"); return 0;}
主要区别就是C类的func函数不是虚函数,那么pc->func()输出仍旧是C,因为动态编联的实现只要求基类为虚函数即可,因为基类有虚函数,那么基类必然有虚指针,子类也就必然有虚指针了。所以动态编联不需要额外定义子类为虚函数。
来源:https://www.cnblogs.com/pangxiaodong/archive/2011/10/12/2208320.html