尝试实现克隆模式,但坚持使用函数调用顺序:
我有一个带有多态类(Script)矢量的 Base 类。
基础类实现了一个克隆函数,它实质上是自己的所有成员(mScripts vector)的副本。
派生类还实现了自己的克隆功能版本,并负责其成员克隆。这个时刻只是一个整数。
问题:我应该如何调用基础类'克隆功能,在派生类'克隆函数,所以每个类都负责克隆自己的成员?
作为一个丑陋的解决方法,现在,我所有的衍生课程'克隆函数手动执行mScripts向量克隆,基本上重复相同的代码。
class Base
{
public:
virtual std::unqique_ptr<Base> clone()
{
std::unique_ptr<Base> clonedInstance = std::make_unique<Base>();
//clone the underlying vector
for(int i = 0; i < mScripts.size(); ++i)
{
clonedInstance->mScripts.push_back(std::move(mScripts[i]->clone()));
}
return std::move(clonedInstance);
}
std::vector<std::unique_ptr<ScriptBase>> mScripts; //polymorphic array
};
class Derived : public Base
{
public:
Derived(const int x) : Base(), mX(x)
{
}
std::unqique_ptr<Base> clone()
{
//calling base::clone() here?
return std::unique_ptr<Base> clonedInstance = std::make_unique<Derived>(mX);
}
private:
int mX;
};
答案 0 :(得分:2)
正确实现复制构造函数,然后每个克隆函数只是return std::make_unique<Derived>(*this);
class Base
{
public:
Base() = default;
Base(const Base& rhs) // default is not fine here
{
for (const auto& script : rhs.mScripts)
{
mScripts.push_back(script->clone());
}
}
virtual ~Base() = default;
virtual std::unique_ptr<Base> clone() const
{
return std::make_unique<Base>(*this);
}
std::vector<std::unique_ptr<ScriptBase>> mScripts; //polymorphic array
};
class Derived : public Base
{
public:
Derived(int x) : Base(), mX(x) {}
Derived(const Derived&) = default; // Default is fine here
std::unique_ptr<Base> clone() const override
{
return std::make_unique<Derived>(*this);
}
private:
int mX;
};
答案 1 :(得分:1)
例如,定义一个接受Base
作为参数的附加构造函数。如果您不想公开它,请将其设为private
:
struct Base {
Base(Base &&) = default;
};
class Derived: public Base {
Derived(Base &&b, int x): Base(std::move(b)), mX(x) {}
public:
std::unique_ptr<Base> clone() const {
auto retBase{Base::clone()};
return std::make_unique<Derived>(std::move(*retBase), mX);
}
};
(无论如何,您的Base
并非易于复制。)
另一种方法是添加模板化克隆,当所有Base
克隆在类似CRTP的模板化函数内完成时,可能会对返回值进行进一步调整:
class Base {
protected:
template<typename Concrete> std::unique_ptr<Base> recreate() const {
std::unique_ptr<Base> retVal{std::make_unique<Concrete>()};
// ???????
return retVal;
};
public:
virtual std::unique_ptr<Base> clone() const { return recreate<Base>(); }
};
struct Derived: public Base {
std::unique_ptr<Base> clone() const {
auto retVal{recreate<Derived>()};
retVal->mX = mX;
return retVal;
}
};