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

标签 c++ virtual

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

相关文章:

c++ - 有没有一种方法可以在不捕获 lambda 变量的情况下编写更短的代码?

delphi - Delphi XE 中有带标题的虚拟列表框吗?

python - Conda:创建虚拟环境

c++ - 虚拟的弃用协变返回类型

c++ - 为什么在 C++ 中 'virtual' 和 '=0' 都需要描述一个方法是抽象的?

c++ - cmake多库场景

c++ - std::vector 带有指向具有自定义类型的静态数组的指针

python - Virtualenv 和 Python ucs-4

C++ for 循环(c++11 方式和旧版本方式)

c++ - SFINAE 使用 VoidT 和不同的编译器会导致不同的结果