单继承,多继承,虚拟继承,sizeof大小

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,因为动态编联的实现只要求基类为虚函数即可,因为基类有虚函数,那么基类必然有虚指针,子类也就必然有虚指针了。所以动态编联不需要额外定义子类为虚函数。

posted @ 2011-10-12 11:13  xiaodongrush  阅读(1560)  评论(1编辑  收藏  举报