gpt4 book ai didi

c++ - 难以理解虚拟和非虚拟函数调用

转载 作者:行者123 更新时间:2023-11-30 01:22:22 25 4
gpt4 key购买 nike

我对以下代码段和输出有一些理解问题。任何人都可以主要解释为什么 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com