我有一个具有多级继承的类层次结构。
cloneable
声明返回cloneable *
的纯虚拟成员函数。base
派生自cloneable
,但未声明任何成员函数。 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;
}
注意:我故意省略了虚拟析构函数来缩短代码示例。
答案 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();
}