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

时间:2018-10-08 18:51:41

标签: 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!

在告诉同辈之前,我仔细检查了google是否发现可能建议在继承的类上使用virtual的所有内容。他们说是的,标准中需要虚拟的,但是编译器大多数时候会自动为继承的类填充虚拟。根据我的理解(我相信大多数程序员),当您想通过多态性覆盖该功能时,就需要虚拟的。但是尚不清楚您是否也需要标记子类函数的实现。

我对该主题缺乏资源感到惊讶。那是什么在现代C ++编译器中是否隐含虚拟的?该标准在何处进行了描述?

1 个答案:

答案 0 :(得分:2)

覆盖虚拟功能的功能是虚拟的。这不是这里的问题。

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