C ++父类调用子虚函数

时间:2008-10-23 23:58:34

标签: c++ inheritance virtual

我想要一个纯虚拟父类来调用像这样的函数的子实现:

class parent
{
  public:
    void Read() { //read stuff }
    virtual void Process() = 0;
    parent() 
    {
        Read();
        Process();
    }
}
class child : public parent
{
  public:
    virtual void Process() { //process stuff }
    child() : parent() { }
}

int main()
{
   child c;
}

这应该可行,但我得到一个未链接的错误:/这是使用VC ++ 2k3

或者它应该不起作用,我错了吗?

7 个答案:

答案 0 :(得分:19)

以下文章的标题说明了所有内容:Never Call Virtual Functions during Construction or Destruction

答案 1 :(得分:4)

或者,创建一个工厂方法来创建对象并使构造函数成为私有,然后工厂方法可以在构造之后初始化对象。

答案 2 :(得分:2)

通常可以工作,但不适用于纯虚基类的构造函数中的调用。在构造基类时,子类覆盖不存在,因此您无法调用它。只要你构建整个对象就调用它,它应该可以工作。

答案 3 :(得分:2)

这是因为你的调用是在构造函数中。派生类在构造函数完成之前是无效的,因此编译器正确地指责你。

有两种解决方案:

  1. 在派生类的构造函数
  2. 中调用Process()
  3. 为Process定义一个空白函数体,如下例所示:
  4. class parent
    {
      public:
        void Read() { //read stuff }
        virtual void Process() { }
        parent() 
        {
            Read();
            Process();
        }
    }
    

答案 4 :(得分:2)

再多一步你可以介绍一些像

这样的功能
class parent
{
    public:
        void initialize() {
            read();
            process();
        }
}

答案 5 :(得分:0)

在完全构造对象之后,您需要在一个调用虚方法的对象内部进行包装:

class parent
{
  public:
    void Read() { /*read stuff*/ }
    virtual void Process() = 0;
    parent()
    {
        Read();
    }
};

class child: public parent
{
  public:
    virtual void Process() { /*process stuff*/ }
    child() : parent() { }
};

template<typename T>
class Processor
{
    public:
        Processor()
            :processorObj() // Pass on any args here
        {
            processorObj.Process();
        }
    private:
        T   processorObj;

};




int main()
{
   Processor<child> c;
}

答案 6 :(得分:0)

表面问题是你调用了一个尚未知道的虚函数(对象是从父对子构造的,因此vtable也是如此)。你的编译器警告过你。

根据我的意见,必要问题是您尝试通过继承重用功能。这几乎总是一个坏主意。一个设计问题,可以这么说:)

基本上,您尝试实例化模板方法模式,在时将 分开:首先读取一些数据(以某种方式),然后处理它(在某种方式)。

使用聚合可能会更好:将Processing函数提供给在正确的时间调用的Template方法。也许你甚至可以为Read功能做同样的事情。

聚合可以通过两种方式完成:

  1. 使用虚拟功能(即运行时绑定)
  2. 使用模板(即编译时间绑定)
  3. 示例1:运行时绑定

    class Data {};
    class IReader    { public: virtual Data read()            = 0; };
    class IProcessor { public: virtual void process( Data& d) = 0; };
    
    class ReadNProcess {
    public:
        ReadNProcess( IReader& reader, IProcessor processor ){
           processor.process( reader.read() );
        }
    };
    

    示例2:编译时绑定

    template< typename Reader, typename Writer > // definitely could use concepts here :)
    class ReadNProcess {
    public:
         ReadNProcess( Reader& r, Processor& p ) {
             p.process( r.read() );
         }
    };