虚拟函数未返回具有多级继承的派生类型
Virtual function not returning derived type with multi-level inheritance
我有一个具有多个继承级别的类层次结构。
cloneable
声明了一个返回cloneable *
的纯虚拟成员函数base
派生自cloneable
,但不声明任何成员函数- 最后,
derived
从base
派生并定义了虚拟函数,但将返回类型重写为derived *
通过指向derived
对象的base
指针调用虚拟函数将返回cloneable *
。我期望base *
,因为虚拟函数的实现返回可转换为base *
的derived *
。这是怎么回事?
如果我在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;
}
注意:为了缩短代码示例,我特意省略了虚拟析构函数。
您认为编译器应该如何猜测您想要一个返回base*
的版本,而不需要任何声明?
虽然上面的问题回答了你的直接问题,但我觉得我也应该补充一些建议。
首先,
- 确实使
clone
函数成为const
,以便可以在const
对象上或通过右值表达式调用它
即
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();
}
相关文章:
- 大小虚拟继承中的派生类
- 继承时如何构建派生类的变量?
- 如何使用 C++ 中的继承函数访问派生类中的局部变量
- 派生类是从基类继承 v 指针并仅使用它,还是也有自己的 v 指针?
- "std::shared_from_this"不能由其派生类继承吗?
- 继承的数据如何在派生类中放置(排列)?
- C++具有空派生类对象的继承大小
- C++ 继承:基类中重载 operator+ 的 2 次在派生类中无法正常工作
- 如何调用继承的重载运算符<<并在派生类的输出中添加更多文本?
- 在模板派生类中继承具有类型别名的构造函数
- C++继承从基类指针访问派生类中的非虚拟函数
- C++排除通过派生类中的基类继承的类
- 派生类调用使用非继承成员的继承函数
- 多重继承中的派生类的行为类似于聚合
- 在派生类中具有相同签名但继承为受保护的函数
- 继承:派生类的基类属性可访问性
- 继承派生的类构造函数
- 为C++中具有多个继承派生类的vtables的基之一调用赋值运算符
- 将抽象类(仅纯虚函数)的继承/派生限制到某个类
- 多重继承派生类:如何在不重复调用 base 的情况下重用派生函数