编译时继承 类 中的隐式虚拟与显式虚拟

Implicit virtual vs explicit virtual in inherited classes at compile time

TL;DR 我引用的旧代码不符合 C++。令人惊奇的是,代码曾经有效。您不能在构造函数和析构函数中调用虚方法。

我和一位同行讨论了 C++ 中的 virtual 关键字。在较旧的 ubuntu OS 上,我正在开发一个程序,该程序报告有关调用 "pure virtual methods" 的错误,这本不应该发生

class Base {
    virtual ~Base() { this->DoSomethingElse(); }
    virtual bool DoSomething() = 0;
    virtual bool DoSomethingElse() = 0;
};

class Foo : public Base {
    ~Foo();
    bool DoSomething();
    bool DoSomethingElse();
};

// Later...
Base* obj = new Foo();
obj->DoSomething(); // Pure virtual function called SIGABORT
delete obj; // Pure virtual function called SIGABORT

通过调试器后,我终于在继承的 classes

上添加了 virtual
class Base {
    virtual ~Base() { this->DoSomethingElse(); }
    virtual bool DoSomething() = 0;
    virtual bool DoSomethingElse() = 0;
};

class Foo : public Base {
    virtual ~Foo();
    virtual bool DoSomething();
    virtual bool DoSomethingElse();
};

// Later...
Base* obj = new Foo();
obj->DoSomething(); // Ok!
delete obj; // Ok!

在告诉我的同伴之前,我仔细检查了 google 是否有任何暗示继承 class 需要 virtual 的东西。他们说是的,标准中需要 virtual,但大多数时候编译器会自动为继承的 classes 填充 virtual。根据我的理解(并且我相信大多数程序员),当您想通过多态性覆盖该函数时,需要 virtual 。但不清楚您是否也需要标记子 class 函数实现。

我对缺乏关于该主题的资源感到惊讶。那是什么? virtual 在现代 C++ 编译器中隐含吗?标准在哪里描述了它?

覆盖虚函数的函数是虚函数。这不是这里的问题。

问题是在 Base 的析构函数 中调用 DoSomethingElse()(有或没有多余的 this->。当构造函数或析构函数调用虚函数时,它会分派到属于 class 的函数版本,其构造函数或析构函数被调用, 而不是 的版本class 源自 class。所以在析构函数中调用 Base::DoSomethingElse(),这是对纯虚函数的调用,这就是运行时中止的原因。