如何在C++; 我定义C++中的两个类。一个是基类,一个是派生类 class CBaseClass { … } class CDerivedClass : public CBaseClass { … }
并希望实现如下克隆功能:如何在C++; 我定义C++中的两个类。一个是基类,一个是派生类 class CBaseClass { … } class CDerivedClass : public CBaseClass { … },c++,clone,C++,Clone,并希望实现如下克隆功能: CBaseClass *Clone(const CBaseClass *pObject) { } 当CDerivedClass的对象传递给Clone时,该函数还将创建CDerivedClass对象并返回。 当CBaseClass的对象传递给Clone时,该函数还将创建CBaseClass对象并返回 如何实现此功能?您可以通过虚拟克隆方法和帮助器模板CRTP类来实现此接口: class CBaseClass { //... vir
CBaseClass *Clone(const CBaseClass *pObject)
{
}
当CDerivedClass的对象传递给Clone时,该函数还将创建CDerivedClass对象并返回。
当CBaseClass的对象传递给Clone时,该函数还将创建CBaseClass对象并返回
如何实现此功能?您可以通过虚拟克隆方法和帮助器模板CRTP类来实现此接口:
class CBaseClass {
//...
virtual CBaseClass * Clone () = 0;
std::unique_ptr<CBaseClass> UniqueClone () {
return std::unique_ptr<CBaseClass>(Clone());
}
virtual std::shared_ptr<CBaseClass> SharedClone () = 0;
};
template <typename DERIVED>
class CBaseClassCRTP : public CBaseClass
{
CBaseClass * Clone () {
return new DERIVED(*static_cast<DERIVED *>(this));
}
std::shared_ptr<CBaseClass> SharedClone () {
return std::make_shared<CbaseClass>(*static_cast<DERIVED *>(this));
}
};
class CDerivedClass : public CBaseClassCRTP<CDerivedClass>
{
//...
};
class-cbase类{
//...
虚拟CBaseClass*克隆()=0;
std::unique_ptr UniqueClone(){
返回std::unique_ptr(Clone());
}
虚拟std::shared_ptr SharedClone()=0;
};
模板
CBaseClassCRTP类:公共CBaseClass类
{
CBaseClass*克隆(){
返回新的派生(*static_cast(this));
}
std::shared_ptr SharedClone(){
返回std::make_shared(*static_cast(this));
}
};
类别CDerivedClass:公共CBaseClassCRTP
{
//...
};
现在,每个派生类都获得了helper类提供的克隆方法。这里是一个简单的解决方案。记住为继承中的每个类提供一个克隆
class Base
{
public:
virtual ~Base() {}
virtual Base *Clone() const
{
// code to copy stuff here
return new Base(*this);
}
};
class Derived : public Base
{
public:
virtual Derived *Clone() const
{
// code to copy stuff here
return new Derived(*this);
}
};
虚拟克隆模式通常用于解决此类问题。经典的解决方案倾向于对
clone()
方法使用同变量返回类型。另一种解决方案是在基类和派生类之间注入工厂类型类(使用CRTP)。甚至有一些解决方案只是通过宏实现此功能。看到了,还有一个。这些解决方案中的任何一个都是可行的,最合适的解决方案将取决于使用和打算使用它们的环境
一种经典的方法,使用并结合更现代的RAII技术(shared_ptr
et.al.)提供了非常灵活和安全的组合。协变返回类型的优点之一是,您可以在层次结构中获得与参数相同级别的克隆(即,返回并不总是到基类)
解决方案确实需要访问共享的\u ptr
和/或唯一的\u ptr
。如果您的编译器不支持,boost会提供这些选项。clone\u shared
和clone\u unique
以标准库中相应的make\u shared
和make\u 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);
}
#包括
#包括
#包括
类CBASE类{
公众:
虚拟CBaseClass*克隆()常量{
返回新的CBaseClass(*此);
}
};
类别CDerivedClass:公共CBaseClass{
公众:
虚拟CDerivedClass*克隆()常量{
返回新的CDerivedClass(*此);
}
};
类别CMoreDerivedClass:公共CDerivedClass{
公众:
虚拟CMoreDerivedClass*克隆()常量{
返回新的CMoreDerivedClass(*此);
}
};
类别CAnotherDerivedClass:公共CBase类别{
公众:
虚拟CAnotherDerivedClass*克隆()常量{
返回新的CAnotherDerivedClass(*本);
}
};
//克隆工厂
模板
std::unique\u ptr clone\u unique(T&&source)
{
static_assert(std::是::value的_base_),
“只能克隆指向目标类型(或其基类型)的指针”;
返回std::unique_ptr(source->clone());
}
模板
std::shared\u ptr clone\u shared(T&&source)
{
static_assert(std::是::value的_base_),
“只能克隆指向目标类型(或其基类型)的指针”;
返回std::shared_ptr(source->clone());
}
int main()
{
std::unique_ptr mdc(新的CMoreDerivedClass());/=std::make_unique();
std::shared_ptr cloned1=clone_shared(mdc);
std::unique_ptr cloned2=克隆_unique(mdc);
const std::unique_ptr cloned3=clone_unique(mdc);
//这些都会生成编译器错误
//std::unique_ptr cloned4=克隆_unique(mdc);
//std::unique_ptr cloned5=克隆_unique(mdc);
//auto cloned6=克隆唯一(mdc);
}
我添加了一个CMoreDerivedClass
和CAnotherDerivedClass
,以稍微扩展层次结构,更好地显示类型检查等
虚拟成员函数
clone
如何?clone
应该是由您层次结构中的每个类实现的虚拟成员方法,包括CDerivedClass
如果您有一个基指针并且不知道确切的类型,可能会发生什么情况?您应该返回DERIVED*
dynamic\u cast
是不必要的,您应该在此处使用智能指针。必须将要克隆的对象传递到克隆函数中似乎有些奇怪。我习惯于这样调用克隆:cloned\u object=some\u object.clone()
。您要克隆的东西将由std::unique\u ptr
管理,这似乎很奇怪;它大概是在克隆之后完成的,不需要任何进一步的管理。@Puppy协变返回与unique_ptr不兼容,所以我放弃了。如果你有更好的解决方案,请告诉我。@NeilKirk:你唯一需要克隆的时候是当你不知道最派生的类型时,因此,简单地返回一个我能想到的std::unique_ptr
并没有什么坏处。在这里使用协变返回有什么好处?@Puppy克隆时,你到底为什么不使用原始指针?你为什么要用CRTP让工作超负荷?第一个可能是设计错误,CRTP只是不必要的额外复杂性。我同意Mooning Duck的观点,它们应该与unique\u ptr
无关,但如果协变返回很重要,您可以创建一个make
样式,类似于make\u unique
,立即将其绑定到所需的唯一\u ptr
的工厂。您需要调用make\u shared
,以避免克隆共享指针时的内存分配开销。@jxh,这一点很好<代码>使_共享尽管创建对象