我对以下代码段和输出有一些理解问题。任何人都可以主要解释为什么 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 时的断点异常;为什么?
最佳答案
每当您在指向派生类对象的基类指针上调用delete
时,基类必须具有虚拟
析构函数。不这样做会导致未定义的行为。
因此,您的类 AS
需要提供一个 virtual
析构函数:
class AS
{
public:
virtual ~AS(){}
};
您的困惑似乎是通过构造函数和析构函数调用的 virtual
函数的输出。
构造函数和析构函数中this
的类型 是调用构造函数/析构函数的类的类型。因此,来自构造函数和析构函数的任何 virtual
函数调用都不会显示您通常对虚函数期望的动态调度行为。而是调用该特定类的函数。
至于尺寸类对象。您不应该假设尺寸是特定的。编译器可以自由添加填充字节,这甚至可能增加非多态类的大小。对于多态类,通常大多数实现都会添加一个指向类对象的虚拟指针,以实现动态调度机制,从而增加对象的大小。请注意,这完全取决于实现。
因此,始终只使用 sizeof
获取大小,永远不要依赖它来确定任何特定值。
关于c++ - 难以理解虚拟和非虚拟函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16433166/