在构造函数中调用纯虚函数会导致错误。

4
class a //my base class
 {
public:
    a()
    {
        foo();
    }
  virtual void foo() = 0;
};



class b : public a
{
    public:
    void foo()
    {
    }
};

int main()
{
    b obj; //ERROR:  undefined reference to a::foo()
}

为什么会出现错误?纯虚函数foo已被定义。我需要在构造函数中调用基类的纯虚方法,请问我需要修改代码哪些部分才能让它正常工作?
3个回答

15

在构造函数中调用虚函数被认为是不好的做法

在派生类对象的基类构造期间,该对象的类型是基类。虚函数不仅解析为基类,而且使用运行时类型信息(例如dynamic_cast(参见Item 27)和typeid)的语言部分将对象视为基类类型。

因此,你对b进行实例化时会调用a的构造函数。这将调用foo(),但是被调用的是a上的foo()。这(当然)是未定义的。


我明白了,我会更改设计。 - user1873947
将类设为抽象类能解决这个问题吗? - Falaque
1
@Falaque - 我不这么认为。请参阅Scott Meyers的相关文章。 - Brian Agnew
@user1873947,指的是类'a'(请参见问题中的示例)。 - Falaque
@BrianAgnew,你或其他人能否提出更好的模式/设计建议? - Falaque

2

引自Yashwant Kanetkar的书《Let Us C++》

始终调用当前类的成员函数,也就是说,在构造函数中虚拟机制不起作用。

因此,将调用class afoo()。由于它被声明为纯虚函数,因此会报错。


它会报错...或者编译通过但会导致未定义行为,如果你幸运的话会崩溃。无论哪种情况,都不要这样做。 - underscore_d

1

在类a的构造函数中调用foo函数,此时对象b尚未完全构造,因此其foo实现不可用。

引自"Effective C++":

不要在构造或析构期间调用虚函数,因为这样的调用永远不会到达比当前正在执行的构造函数或析构函数更派生的类。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接