带有智能指针的虚拟构造函数习惯用法
virtual constructor idiom with smart pointers
我有一个多态类的层次结构,比如Shape
抽象基类及其派生类,例如Rectangle
、Circle
等。遵循虚拟构造函数习语,我想知道为什么在使用智能指针时,派生类中的虚拟构造函数函数的返回类型应该返回与其父类中相同的类型
例如,请参阅下面的代码,其中clone()
和create()
成员函数需要将smart_pointers
返回给Shape
类。但是,当使用simple pointers
时,返回类型可以与派生类的类型相同
有人能解释一下为什么我们需要以提到的方式处理这些功能吗?
class Shape;
typedef std::unique_ptr<Shape> shape_ptr;
class Shape{
public:
//typedef std::unique_ptr<Shape> shape_ptr;
Shape(){};
virtual ~Shape(){};
virtual void draw() const = 0;
virtual float area() const = 0;
virtual shape_ptr clone() const = 0;
virtual shape_ptr create() const = 0;
//virtual Shape*clone() const = 0;
//virtual Shape*create() const = 0;
};
class Rectangle:public Shape{
public:
typedef std::unique_ptr<Rectangle> rectangle_SmartPtr;
Rectangle(int height=0, int width=0):m_Height(height),m_Width(width){};
Rectangle(const Rectangle & rect):m_Height(rect.m_Height),m_Width(rect.m_Width){};
~Rectangle(){};
virtual void draw() const;
virtual float area() const;
//virtual rectangle_SmartPtr clone() const{ return rectangle_SmartPtr(new Rectangle(*this)); };
// error C2555: 'Rectangle::clone': overriding virtual function return type differs and is not covariant from 'Shape::clone'
//virtual rectangle_SmartPtr create() const{ return rectangle_SmartPtr(new Rectangle()); };
// error C2555: 'Rectangle::create': overriding virtual function return type differs and is not covariant from 'Shape::create'
virtual shape_ptr clone() const{ return shape_ptr(new Rectangle(*this)); }; //OK
virtual shape_ptr create() const{ return shape_ptr(new Rectangle()); }; //OK
//virtual Rectangle* clone() const{ return new Rectangle(*this); }; //OK
//virtual Rectangle* create() const{ return new Rectangle(); }; //OK
private:
int m_Height;
int m_Width;
};
class Circle:public Shape{
public:
typedef std::unique_ptr<Circle> circle_SmartPtr;
Circle(float radius=0):m_Radius(radius){};
Circle(const Circle & other):m_Radius(other.m_Radius){};
~Circle(){std::cout << "Circle destructor: " << this << std::endl; };
virtual void draw() const;
virtual float area() const;
//virtual circle_SmartPtr clone() const{ return circle_SmartPtr(new Circle(*this)); };
// error C2555: 'Circle::clone': overriding virtual function return type differs and is not covariant from 'Shape::clone'
//virtual circle_SmartPtr create() const{ return circle_SmartPtr(new Circle()); };
// error C2555: 'Circle::create': overriding virtual function return type differs and is not covariant from 'Shape::create'
virtual shape_ptr clone() const{ return shape_ptr(new Circle(*this)); }; //OK
virtual shape_ptr create() const{ return shape_ptr(new Circle()); }; //OK
//virtual Circle* clone() const{ return new Circle(*this); }; //OK
//virtual Circle* create() const{ return new Circle(); }; //OK
private:
float m_Radius;
};
这被称为协方差。
在类层次结构中,当基类指定返回T*
或T&
的虚拟方法时,则允许派生类分别返回U*
或U&
,前提是U
派生自T
(注意:显然还有const
和volatile
的组合)。
这是一个由编译器检查的特殊规则,它之所以有效,是因为如果U
从T
派生,则U*
可以强制转换为T*
。不幸的是,该规则受到限制,因为它不适用于任何转换,因此即使您通常可以从unique_ptr<Rectangle>
构造unique_ptr<Shape>
。。。协方差不起作用。
这就是为什么在其可克隆概念中,Boost要求返回裸指针类型。这很遗憾,但这是获得协方差的唯一方法。
当使用原始指针时,编译器允许协变返回类型,但当使用智能指针时,这是不可能的,因为unique_ptr< Rectangle >
不是从unique_ptr< Shape >
派生的。从编译器的角度来看,这两个类是完全不相关的。
相关文章:
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 没有用于初始化C++中的变量模板的匹配构造函数
- 初始化具有非默认构造函数的std::数组项的更好方法
- 当从函数参数中的临时值调用复制构造函数时
- 在c++构造函数中使用随机字符串生成器
- 为什么内存泄漏只发生在赋值运算符重载的情况下,而不是在复制构造函数中,以及复制和交换习惯用法如何解决它
- 使用检测习惯用法来确定类型是否具有具有特定签名的构造函数
- C++:复制和交换习惯用法,替代构造函数
- 带有智能指针的虚拟构造函数习惯用法
- 如何实现拷贝交换习惯用法的复制构造函数
- 对象构造函数"settings"习惯用法
- 绕过基类构造函数初始化,这是一个坏习惯
- 移动构造函数和赋值操作符,使用复制-交换习惯实现