我在 C++ 中定义了两个类。一个是基类,一个是派生类
class CBaseClass
{
…
}
class CDerivedClass : public CBaseClass
{
…
}
并且想实现一个克隆函数如下:
CBaseClass *Clone(const CBaseClass *pObject)
{
}
当一个CDerivedClass对象被传递给Clone时,那么这个函数也会创建一个CDerivedClass对象并返回。 当一个 CBaseClass 对象被传递给 Clone 时,该函数也会创建一个 CBaseClass 对象并返回。
如何实现这样的功能?
最佳答案
虚拟克隆模式经常被用来解决诸如此类的问题。经典解决方案倾向于为 clone()
方法使用协变返回类型。其他解决方案在基类和派生类之间注入(inject)工厂类型类(使用 CRTP)。甚至还有仅使用宏来实现此功能的解决方案。查看C++ FAQ , C++ idioms和一个 blog on this .这些解决方案中的任何一种都是可行的,最合适的解决方案取决于它们的使用环境和预期使用环境。
经典方法,使用 covariant return types并结合更现代的 RAII 技术(shared_ptr
等)提供了非常灵活和安全的组合。协变返回类型的优点之一是您能够在层次结构中获得与参数相同级别的克隆(即返回并不总是到基类)。
该解决方案确实需要访问 shared_ptr
和/或 unique_ptr
。如果您的编译器不可用,boost 会提供替代方案。 clone_shared
和 clone_unique
以标准库中相应的 make_shared
和 make_unique
实用程序为模型。它们包含对参数和目标类型的类层次结构的显式类型检查。
#include <type_traits>
#include <utility>
#include <memory>
class CBaseClass {
public:
virtual CBaseClass * clone() const {
return new CBaseClass(*this);
}
};
class CDerivedClass : public CBaseClass {
public:
virtual CDerivedClass * clone() const {
return new CDerivedClass(*this);
}
};
class CMoreDerivedClass : public CDerivedClass {
public:
virtual CMoreDerivedClass * clone() const {
return new CMoreDerivedClass(*this);
}
};
class CAnotherDerivedClass : public CBaseClass {
public:
virtual CAnotherDerivedClass * clone() const {
return new CAnotherDerivedClass(*this);
}
};
// Clone factories
template <typename Class, typename T>
std::unique_ptr<Class> clone_unique(T&& source)
{
static_assert(std::is_base_of<Class, typename std::decay<decltype(*source)>::type>::value,
"can only clone for pointers to the target type (or base thereof)");
return std::unique_ptr<Class>(source->clone());
}
template <typename Class, typename T>
std::shared_ptr<Class> clone_shared(T&& source)
{
static_assert(std::is_base_of<Class, typename std::decay<decltype(*source)>::type>::value,
"can only clone for pointers to the target type (or base thereof)");
return std::shared_ptr<Class>(source->clone());
}
int main()
{
std::unique_ptr<CDerivedClass> mdc(new CMoreDerivedClass()); // = std::make_unique<CMoreDerivedClass>();
std::shared_ptr<CDerivedClass> cloned1 = clone_shared<CDerivedClass>(mdc);
std::unique_ptr<CBaseClass> cloned2 = clone_unique<CBaseClass>(mdc);
const std::unique_ptr<CBaseClass> cloned3 = clone_unique<CBaseClass>(mdc);
// these all generate compiler errors
//std::unique_ptr<CAnotherDerivedClass> cloned4 = clone_unique<CAnotherDerivedClass>(mdc);
//std::unique_ptr<CDerivedClass> cloned5 = clone_unique<CBaseClass>(mdc);
//auto cloned6 = clone_unique<CMoreDerivedClass>(mdc);
}
我添加了一个 CMoreDerivedClass
和 CAnotherDerivedClass
来稍微扩展层次结构以更好地显示类型检查等。
关于c++ - 如何在 C++ 中克隆为派生对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24939570/