我对以下代码段和输出有一些理解问题。任何人都可以提供一个解释,主要是为什么test()按照输出中的方式工作。我正在使用MSCV 2008 C ++编译器。
class AS
{
int a;
public:
AS():a(1){show();}
virtual void show() {cout<<a<<endl;}
void test() { cout<<"Calling show()"<<endl; this->show();}
};
class BS: virtual public AS
{
int b;
public:
BS():b(2){show();}
virtual void show() {cout<<b<<endl;}
void test() { cout<<"Calling show()"<<endl; this->show();}
};
class CS:public virtual AS
{
int c;
public:
CS():c(3){show();}
virtual void show() {cout<<c<<endl;}
void test() { cout<<"Calling show()"<<endl; this->show();}
};
class DS:BS, public CS
{
int d;
public:
DS():d(4){show();}
virtual void show() {cout<<d<<endl;}
void test() { cout<<"Calling show()"<<endl; this->show();}
};
int main()
{
cout<<"Class Sizes:"<<endl;
cout<<sizeof(AS)<<endl;
cout<<sizeof(BS)<<endl;
cout<<sizeof(CS)<<endl;
cout<<sizeof(DS)<<endl;
AS* aa = new DS();
aa->test();
aa->show();
delete aa;
return 0;
}
输出是: -
Class Sizes:
8
20
20
32
1
2
3
4
Calling show()
4
4
和删除aa时的断点异常;为什么?
答案 0 :(得分:5)
每当您在指向派生类对象的基类指针上调用delete
时,基类必须具有virtual
析构函数。如果不这样做会导致未定义的行为。
因此,您的班级AS
需要提供virtual
析构函数:
class AS
{
public:
virtual ~AS(){}
};
您的混淆似乎是通过构造函数和&amp ;;调用的virtual
函数的输出。析构函数。
构造函数和析构函数中this
的类型是正在调用构造函数/析构函数的类的类型。因此,构造函数和析构函数中的任何virtual
函数调用都不会显示您通常期望的虚函数的动态调度行为。而是调用该特定类的函数。
对于size类对象。你不应该假设尺寸是特定的。编译器可以自由添加填充字节,这可能会增加甚至非多态类的大小。对于多态类,通常大多数实现将向类对象添加虚拟指针以实现动态分派机制,从而增加对象大小。请注意,这完全取决于实现
因此,始终只需使用sizeof
获取大小,并且永远不要依赖它是任何特定的。
答案 1 :(得分:0)
这是我的一点,如果我错了,请纠正我。
[注意:vptr-vtable机制用于实现虚函数调用,而vbptr(虚基类指针)用于实现虚基类。 此外,sizeOf(某些多态类)可能会因使用的编译器+平台而有所不同]
1)类AS的实例需要8个字节 (“int a”为4个字节,隐藏vptr为4个字节)= 8
2)BS类的实例需要20个字节
(4字节保存基类AS + 4字节填充+ 4字节表示“int b”+ 4字节表示隐藏vptr + 4字节表示vbptr)= 20
3)类CS的实例需要20个字节
(4字节保存基类AS + 4字节填充+ 4字节表示“int c”+ 4字节表示隐藏的vptr + 4字节表示vbptr)= 20
4)类DS的实例需要32个字节
(4个字节用于保存共享基类AS + 4个字节用于“int d”+ 8个字节用于保存基类BS(占成员大小+ vbptr大小)+ 8个字节用于保存基类CS(占成员大小+ vbptr大小)+ 4个字节用于隐藏DS :: vptr + 4个字节用于DS :: vbptr )= 32
[请注意,在实现vptr-vtable机制时,编译器使用虚函数地址扩充vtable,在DS类的内存模型中存在单个v-table和单个v-ptr。然而,vbptr将在每个虚拟基类中以及从它们继承的内部类中重复。
同样,所有这些都是编译器特定的实现,并且可能因编译器而异。
此外,将所有基类析构函数定义为虚拟以消除崩溃。