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

  • 本文关键字:虚拟 继承 编译 c++ virtual gnu
  • 更新时间 :
  • 英文 :


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

我和一位同行在C++中讨论了virtual关键字。在较旧的 ubuntu 操作系统上,我正在开发一个程序,该程序报告了有关调用"纯虚拟方法"的错误,这不应该发生

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

单步执行调试器后,我终于在继承的类上添加了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!

在告诉我的同龄人之前,我仔细检查了谷歌是否有任何可能表明继承类需要virtual的东西。他们说,是的,标准中需要虚拟,但编译器大多数时候会自动为继承的类填充虚拟。根据我的理解(我相信大多数程序员(,当你想通过多态性覆盖该功能时,虚拟是需要的。但不清楚您是否也需要标记子类函数实现。

我对缺乏有关该主题的资源感到惊讶。那是什么呢?虚拟在现代C++编译器中是否隐含,标准在哪里描述?

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

问题是在析构函数中调用DoSomethingElse()(有或没有冗余this->(Base。当构造函数或析构函数调用虚函数时,它会调度到属于要调用其构造函数或析构函数的类的函数版本,而不是调度到从该类派生的类的版本。因此,析构函数中的调用调用Base::DoSomethingElse(),这是对纯虚函数的调用,这就是运行时中止的原因。

最新更新