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

冷暖自知 提交于 2020-01-24 23:48:34

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!