问题描述
我有两个向量。我在一个向量中注册派生类,然后想要制作副本并将它们复制到另一个向量。我试图这样做是为了避免基类切片,但能够拥有类的“模板”,用于生成可以从中变异的新对象。
如何克隆 unique_ptr
指向的对象并拥有一个可以存储在 unique_ptr
中的新 vector
?
下面显示的想法是我可以在 active
中拥有类的多个副本,同时在 available
中仍然拥有原始对象。或者,是否有更好的架构来尝试制作派生类的副本以进行存储?
#include <iostream>
#include <memory>
#include <vector>
class BaseClass {
virtual void doSomething(){}
};
class DerivedClass1: public BaseClass {
public:
float myVar1;
void doSomething() override { std::cout << "1"; }
};
class DerivedClass2: public BaseClass {
public:
int myVar2;
void doSomething() override { std::cout << "2"; }
};
std::vector<std::unique_ptr<BaseClass>> available;
std::vector<std::unique_ptr<BaseClass>> active;
void registerClass( std::unique_ptr<BaseClass> newAvailable ) {
available.push_back(std::move(newAvailable));
}
void makeActive() {
for( auto &tomakeActive : available ) {
// todo: ?? // active.push_back( available->clone() );
}
}
int main() {
std::unique_ptr<DerivedClass1> derived1 = std::make_unique<DerivedClass1>();
std::unique_ptr<DerivedClass2> derived2 = std::make_unique<DerivedClass2>();
registerClass( std::move( derived1 ) );
registerClass( std::move( derived2 ) );
makeActive();
makeActive();
return 0;
}
解决方法
如何克隆 unique_ptr
指向的对象并拥有一个可以存储在 unique_ptr
中的新 vector
?
C++ 没有自动处理这个的工具,你必须在每个派生类中手动实现它,例如:
#include <iostream>
#include <memory>
#include <vector>
class BaseClass {
virtual void doSomething(){}
virtual std::unique_ptr<BaseClass> clone() = 0;
};
class DerivedClass1: public BaseClass {
public:
float myVar1;
void doSomething() override { std::cout << "1"; }
std::unique_ptr<BaseClass> clone() override { return std::make_unique<DerivedClass1>(*this); }
};
class DerivedClass2: public BaseClass {
public:
int myVar2;
void doSomething() override { std::cout << "2"; }
std::unique_ptr<BaseClass> clone() override { return std::make_unique<DerivedClass2>(*this); }
};
std::vector<std::unique_ptr<BaseClass>> available;
std::vector<std::unique_ptr<BaseClass>> active;
void registerClass( std::unique_ptr<BaseClass> newAvailable ) {
available.push_back(std::move(newAvailable));
}
/* alternatively:
template<class T>
void registerClass() {
available.push_back(std::make_unique<T>());
}
*/
void makeActive() {
for( auto &toMakeActive : available ) {
active.push_back( available->clone() );
}
}
int main() {
registerClass( std::make_unique<DerivedClass1>() );
registerClass( std::make_unique<DerivedClass2>() );
/* alternatively:
registerClass<DerivedClass1>();
registerClass<DerivedClass2>();
*/
makeActive();
makeActive();
return 0;
}