虛擬克隆模式通常用於解決這些問題。經典解決方案傾向於對clone()
方法使用協變式返回類型。其他解決方案在基類和派生類之間注入工廠類型類(使用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
擴大層次一點點,以便更好地展示各類檢查等
Sample code
怎麼樣虛成員函數'clone'? –
'Clone'應該是由你的每個層次實現的虛擬成員方法,包括'CDerivedClass' – quantdev
[如何在C++中克隆對象?或者是否有另一種解決方案?](http://stackoverflow.com/questions/12902751/how-to-clone-object-in-c-or-is-there-another-solution) – quantdev