调用基础 class 克隆实现
Calling base class clone implementation
正在尝试实现克隆模式,但坚持函数调用顺序:
我有一个 Base class 带有多态向量 classes(脚本)。
Base class's 实现了一个克隆函数,它本质上是复制它自己及其所有成员(mScripts 向量)。
Derived class's 也实现了自己的克隆函数版本,并负责其成员的克隆。目前只是一个整数。
问题:我应该如何调用Base class'克隆函数,在Derived class' 克隆函数,所以每个 class 都负责克隆自己的成员?
作为一个丑陋的解决方法,现在,我所有的 Derived classes 克隆函数手动执行 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;
};
正确实现拷贝构造函数,那么每个克隆函数就是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;
};
例如,定义一个额外的构造函数,它接受一个 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;
}
};
正在尝试实现克隆模式,但坚持函数调用顺序:
我有一个 Base class 带有多态向量 classes(脚本)。
Base class's 实现了一个克隆函数,它本质上是复制它自己及其所有成员(mScripts 向量)。
Derived class's 也实现了自己的克隆函数版本,并负责其成员的克隆。目前只是一个整数。
问题:我应该如何调用Base class'克隆函数,在Derived class' 克隆函数,所以每个 class 都负责克隆自己的成员?
作为一个丑陋的解决方法,现在,我所有的 Derived classes 克隆函数手动执行 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;
};
正确实现拷贝构造函数,那么每个克隆函数就是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;
};
例如,定义一个额外的构造函数,它接受一个 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;
}
};