2012-09-17 44 views
2

我有一个具有多级继承的类层次结构。虚拟函数不返回具有多级继承的派生类型

  1. cloneable声明一个返回cloneable *的纯虚拟成员函数。
  2. base来自cloneable,但未声明任何成员函数。
  3. 最后,derived来自base并定义了虚函数,但是将返回类型覆盖为derived *

通过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; 
} 

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

回答

4

确切地说,你认为编译器应该如何猜测你想要一个返回base*的版本,而没有任何声明?


尽管上述问题回答了您的直接问题,但我觉得我还应该添加一些建议。

首先,

  • 做使clone功能const,以便它可以在const对象或经由一个rvalue表达被调用。

即,

virtual cloneable* clone() const; 

其次,创建克隆对象的

  • 回报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(); 
} 
+0

你说得对。我认为编译器会隐式地在'base'中声明一个纯虚函数,但即使它确实可能不会覆盖返回类型。所以宣言是必要的。你的三点是有效的:我需要添加const,但是我在“生产”代码中做了一个适当的克隆。我仍然在查看返回unique_ptr的示例代码。很有帮助。谢谢。 – svetianov