虚函数不返回具有多级继承的派生类型

时间:2012-09-17 03:55:38

标签: c++ inheritance virtual-functions

我有一个具有多级继承的类层次结构。

  1. cloneable声明返回cloneable *的纯虚拟成员函数。
  2. base派生自cloneable,但未声明任何成员函数。
  3. 最后,derived派生自base并定义虚函数,但将返回类型覆盖为derived *
  4. 通过指向base对象的derived指针调用虚函数返回cloneable *。我期待base *,因为虚函数的实现返回derived *,可转换为base *。这是怎么回事?

    如果我在base中声明纯虚函数,我终于可以从中获取base *,但我不明白为什么这个声明是必要的。

    代码:

    struct cloneable
    {
      virtual cloneable * clone() = 0;
    };
    
    struct base : cloneable 
    {
    // virtual base * clone() = 0;    // this line resolves the compile error
    };
    
    struct derived : base
    {
      virtual derived * clone () { return new derived; }
    };
    
    int main(int, char**)
    {
      derived d;
      base * bp = &d;
      base * bbp = bp->clone();  // error: invalid conversion 
                                 // from ‘cloneable*’ to ‘base*’      
      return 0;  
    }
    

    注意:我故意省略了虚拟析构函数来缩短代码示例。

1 个答案:

答案 0 :(得分:4)

您认为编译器应该如何猜测您希望版本返回base*而没有任何声明?


虽然上述问题回答了你的直接问题,但我觉得我还应该补充一些建议。

首先,

  • 确实生成clone函数const,以便可以在const对象上或通过右值表达式调用它。

即,

virtual cloneable* clone() const;

其次,要创建对象的 clone

  • 返回new T( *this )(使用复制构造函数),而不是new T(使用默认构造函数)。

第三,

  • 为了安全起见,对于公开的clone操作,返回一个智能指针,例如unique_ptr<MyClass>,而不是原始指针。

但是,通过将返回类型更改为智能指针,您将不再直接受益于协变函数结果的C ++支持,这仅适用于原始指针和引用。因此,一种方法是使用非public原始指针结果实现,它可以具有协变结果类型,并且只是一个返回智能指针的类型化public包装器。实际上,您自己实现了公共接口的协方差,它看起来像这样:

#include <memory>       // std::unique_ptr
using namespace std;

class Base
{
private:
    virtual Base* virtualClone() const
    {
        return new Base( *this );
    }

public:
    unique_ptr< Base > clone() const
    {
        return unique_ptr< Base >( virtualClone() );
    }
};

class Derived
    : public Base
{
private:
    virtual Derived* virtualClone() const
    {
        return new Derived( *this );
    }

public:
    unique_ptr< Derived > clone() const
    {
        return unique_ptr< Derived >( virtualClone() );
    }
};

int main()
{
  Derived d;
  Base* bp = &d;
  unique_ptr< Base > bbp = bp->clone();
}