C++中的虚函数继承问题[转]
#include <iostream> using namespace std; class a { public: virtual void aa(){}; }; class b:public a { public: virtual void aa(){}; virtual void bb(){}; }; class c: public b { public: virtual void aa(){}; virtual void cc(){}; }; int main() { cout<<sizeof(a)<<endl; cout<<sizeof(b)<<endl; cout<<sizeof(c)<<endl; return 0; }
请问这段代码的结果为什么是 4 4 4
追问
sizeof(m)是4。。你说的这些我也知道 ,但是还是没有解决题目里虚函数继承的情况下的类的size的大小问题。
回答
说错了 class m { void f(){} }; 这样m为1。 第2条不是说了吗? ”b和c没有添加任何数据成员,仅仅override函数,所有大小不变。“ 说了一堆不就是说这事吗?基类含有虚函数,单重非virtual继承,并且派生类没有添加新的数据成员,就算继承一万次也是4,vptr还不是那一个吗?类的size会变吗?
追问
把你最关键的一条忘了。。呵呵。不好意思。这下懂了。 我还想问下您下面这道问题: class A { virtual aa(){}; }; class B : public virtual A { }; sizeof(B)= 8; 但是我觉得一方面是指向A的指针+A的大小+B自己指向虚函数的指针(因为他也继承了A的虚函数啊) = 12 望赐教啊。。。。
回答
虚拟继承这块特别复杂。 你说的这个例子“算是”编译器优化,如果换成 class B : public virtual A { virtual void bb(){} }; 结果应该就是你期望的结果。 但是,这个结果也不是绝对的,这个应该是微软编译器给出的结果,换GNU编译器应该不是这结果,应为他们在处理虚拟继承的策略不一样。微软采用了,插入一个指针指向一个table,table里面放的是各个虚拟继承基类的offset。所以这就涉及到两种类型的指针,一个是vptr,一个是暂称为vbc_ptr(virtual base class pointer)。 所以随着virtual继承层数以及多重继承的个数增加,类的内存布局图就复杂得多,事实上,实际工程运用根本用不了那么多,典型的iostream中标准输入输出那中关系已经算比较复杂的了。 另外,针对你的例子在有一些编译器上可能会给出sizeof(B)=4这样的结果,这应该属于编译器优化,一方面因为派生类没添加新虚函数,所以没必要给出新的vptr;另一方面由于基类没有数据成员,所以也没必要插入一个vbc_ptr来间接指向A。 应该是这样的,原来也在这方面下过点功夫,很长时间了,记不大清楚了。换几个编译器,自己反汇编看一下。