何时在构造函数中调用虚函数是安全的

LiK*_*Kao 4 c++ constructor virtual-functions

我有一些代码,我真的想从构造函数调用一个虚方法.我知道这被认为是不安全的,我对对象构造了解得足以理解为什么.我也没有遇到这些问题.目前我的代码正在运行,我认为应该没问题,但我想确定一下.

这是我在做的事情:

我有一些类层次结构,并且有一个普通的公共函数,它像往常一样转发到私有虚方法.但是我确实希望在构造我的对象时调用这个公共方法,因为它将所有数据填充到对象中.我绝对肯定这个虚拟调用来自叶类,因为从类层次结构的任何其他部分使用这个虚方法根本就没有意义.

因此,在我看来,一旦我进行虚拟调用就应该完成对象创建,一切都应该没问题.还有什么可能出错吗?我想我必须用一些重要的注释来标记逻辑的这一部分,以解释为什么这个逻辑永远不会被移动到任何基本条目,即使看起来它可能被移动.但除了其他程序员的愚蠢之外我应该没事,不应该吗?

Die*_*ühl 5

在构造函数或析构函数中调用任何非抽象虚函数是绝对安全的!但是,它的行为可能会令人困惑,因为它可能无法实现预期.在执行类的构造函数时,对象的静态和动态类型是构造函数的类型.也就是说,永远不会将虚函数分派给进一步派生类的重写.除此之外,虚拟调度实际上是有效的:例如,当通过基类指针或引用调用虚函数时,正确地调度到当前构造函数或被破坏的类中的覆盖.例如(可能是拼写错误,因为我目前无法使用此代码):

#include <iostream>
struct A {
    virtual ~A() {}
    virtual void f() { std::cout << "A::f()\n"; }
    void g() { this->f(); }
};
struct B: A {
    B() { this->g(); } // this prints 'B::f()'
    void f() { std::cout << "B::f()\n"; }
};
struct C: B {
    void f() { std::cout << "C::f()\n"; } // not called from B::B()
};

int main() {
    C c;
}
Run Code Online (Sandbox Code Playgroud)

也就是说,如果您不希望将虚函数调度到另一个派生函数,则可以在构造函数或类的析构函数中直接或间接调用虚函数.你甚至可以这样做,只要它被定义,虚拟函数在给定的类中是抽象的.但是,调度未定义的抽象函数会导致运行时错误.

  • 好.在这种情况下,他可能想要考虑C++ 2011,在那里他可以创建类`final`. (2认同)