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

 

 

对比两个所谓的空类:
class m
{
        void virtual f(){}
};

class n
{
        virtual void virtual f(){}
};
在常用的编译器下,sizeof(m)是1,sizeof(n)是4。这是由于m中无数据成员,但是为了确保内存空间的唯一性,编译器会给m中添加一个隐含的char类型;n是4这个解释起来比较复杂,简单说是为了实现虚函数,编译器会在含有虚函数的类里添加一个一般称为vptr指针,这个指针指向虚函数表。

2、b和c没有添加任何数据成员,仅仅override函数,所有大小不变。

3、虚拟继承理解起来要复杂的多,这个例子也没有涉及到。

追问

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。

应该是这样的,原来也在这方面下过点功夫,很长时间了,记不大清楚了。换几个编译器,自己反汇编看一下。






posted @ 2012-09-10 15:30  SA高处不胜寒  阅读(497)  评论(0编辑  收藏  举报