C++ clone()函式的用法
原型模式
在C++中,要拷貝一個物件,除了自定義一個拷貝建構函式來實現物件複製外,還可以實現一個clone函式。這需要藉助編譯器實現的一個隱藏拷貝建構函式,這樣的做法,更省心。
背後的原理是C++的原型(Prototype)模式:用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。
Prototype模式提供了一個通過已存在物件進行新物件建立的介面(Clone), Clone()實現和具體的語言相關,在C++中通過拷貝建構函式實現。
注意:clone函式是virtual的,無法內聯。
示例程式碼:
#include "stdafx.h"
#include <iostream>
class CA
{
public:
int value;
CA* clone() const { return new CA( *this );}
//僅一個建構函式
CA(int a ){value=a;}
};
int _tmain(int argc, _TCHAR* argv[])
{
CA* objA=new CA(10);
CA* objtemp=objA->clone();
delete objA;
std::cout<<objtemp->value;
delete objtemp;
return 0;
}
Prototype 模式的應用場景在於,你拿到一個 Base* ,它指向某個 Derived 物件,你想克隆出 Derived 物件,但程式碼中不寫出 Derived 的具體型別,因為有很多派生類,這種情況下你用建構函式是搞不定的,就需要Prototype 模式了。
原型模式的作用
1、基本就是你需要從A的例項得到一份與A內容相同,但是又互不干擾的例項的話,就需要使用原型模式。
2、用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。這個其實和C++的拷貝建構函式的作用是相似的(但不相同),實際上就是動態抽取 當前物件執行時的狀態。
原型模式的優勢
一.為什麼不用new直接新建物件,而要用原型模式?
首先,用new新建物件不能獲取當前物件執行時的狀態,其次就算new了新物件,在將當前物件的值複製給新物件,效率也不如原型模式高。
二.為什麼不直接使用拷貝建構函式,而要使用原型模式?
原型模式與拷貝建構函式是不同的概念,拷貝建構函式涉及的類是已知的,原型模式涉及的類可以是未知的。
原型模式生成的新物件可能是一個派生類。拷貝建構函式生成的新物件只能是類本身。原型模式是描述了一個通用方法(或概念),它不管是如何實現的,而拷貝構造則是描述了一個具體實現方法。
class base
{
public :
base();
base(base &obj);
virtual ~base();
virtual base *clone() { return new base(*this) ; };
};
class derived : public base
{
public :
derived();
derived( derived &);
virtual base *clone(){return new derived (*this); }
....
};
base *obj1 = new base ;
base *obj2 = new derived ;//基類指標指向派生類物件,怎樣用基類指標建立一個新的派生類物件?? 用基類的拷貝建構函式顯然不行。
base *obj3 = obj1 .clone();
base *obj4 = obj12.clone();
適用場景
1.資源優化場景
類初始化需要消化非常多的資源,這個資源包括資料、硬體資源等。
2.效能和安全要求的場景
通過new產生一個物件需要非常繁瑣的資料準備或訪問許可權,則可以使用原型模式。
3.一個物件多個修改者的場景
一個物件需要提供給其他物件訪問,而且各個呼叫者可能都需要修改其值時,可以考慮使用原型模式拷貝多個物件供呼叫者使用。
缺點
1、配備克隆方法需要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不一定很容易,特別當一個類引用不支援序列化的間接物件,或者引用含有迴圈結構的時候。
2、實現原型模式每個派生類都必須實現 Clone介面。
3、逃避建構函式的約束。