【C++】多态对象拷贝
使用多态时,通过Base的指针或引用指向具体子类。在容器中,以Base类型存储,比如:vector<Base*> vec。
我现在期望对vec中的每个对象,都按照其【实际的类型】进行拷贝,怎么做?拷贝构造函数又不可以设为virtual,从而进行多态实施具体行为。
-
设一个
virtual Clone(),让具体的类自己负责自己具体的类型。这是多态拷贝的标准解决方案 -
析构函数一定要设为virtual
-
这是原型模式(prototype pattern)的思想
-
C++支持协变返回类型
也就是
virtual Clone接口,可以返回具体类型的指针或引用,而不是只返回Base*-
C++允许的协变返回类型仅限于原始指针和引用,不适用于智能指针。
-
智能指针和协变两者不兼容的话,在安全性(裸指针or智能指针)、类型信息缺失之间做选择,该如何取舍?
以安全性为前提,优先使用智能指针,类型信息可通过
dynaminc_cast转。如果类型是当前关键需求,必须使用协变,可使用【裸指针+RAII】的方式,在类析构里
class Base { virtual Base* Clone()=0; //定义Clone接口 } class Son1:public Base { Son1(){} Son1(const Son1& another){} //拷贝构造 //virtual Base* Clone() const override virtual Son1* Clone() const override //C++支持协变返回类型,可以返回更具体的指针,返回Son1*而不是Base* { return new Son1(*this); //将当前对象传给本类的拷贝构造,从而返回一个本类的深拷贝对象 } } class Son2:public Base { Son2(){} Son2(const Son2& another){} //拷贝构造 virtual Son2* Clone() const override { return new Son2(*this); } } int main() { std::vector<Base*> vec; vec.push_back(new Son1); vec.push_back(new Son2); std::vector<Base*> vecCopy; for(const auto& item:vec) { vecCopy.push_back(item.Clone()); //返回深拷贝对象,push_back到vecCopy中 } } -
-
使用智能指针管理所有权
防止Clone()中new出来的对象忘记delete。
class Base { virtual std::unique_ptr<Base> Clone() const = 0; } class Son1:public Base { Son1(){} Son1(const Son1& another){} virtual std::unique_ptr<Base> Clone() const override //不能写成std::unique_ptr<Son1>,智能指针不支持协变 { //unique_ptr不允许拷贝,但编译器允许返回右值的unique_ptr。而c++中规定:return的局部变量当作右值处理 //因此返回的是一个右值unique_ptr对象,传入到vec::push_back时,由于C++11起push_back(所有stl容器的插入接口) //有了参数为右值的重载:push_back(T&& value)触发push_back的移动 return std::make_unique<Son1>(*this); } } class Son2:public Base { Son2(){} Son2(const Son2& another){} virtual std::unique_ptr<Base> Clone() const override { return std::make_unique<Son2>(*this); } } int main() { std::vector<std::unique_ptr<Base>> vec; vec.push_back(std::make_unique<Son1>()); vec.push_back(std::make_unique<Son2>()); std::vector<std::unique_ptr<Base>> vecCopy; for(const auto& item:vec) { vecCopy.push_back(item->Clone()); //返回右值unique_ptr,调用右值重载 } } -
CRTP

浙公网安备 33010602011771号