標籤:
1、考慮下面的需求,把一群組類型不同,但是相互關聯的對象放入容器中,比如Animal,Dog,Cat對象。
2、容器只能包含一組 類型相同的對象,Animal,Dog,Cat對象是沒有辦法放入容器中的。
3、怎麼解決上面的問題?
假設容器為vector,可以使用vector<Animal>,這會導致一個新問題,因為vector儲存的是對象副本,子類放入vector<Animal>發生對象切割,不可能具備多態的性質。
怎麼解決上面的問題?
---------------------------------------------------------------------------------------------------------------------
經典的解決辦法:
vector中儲存Animal指標,這會帶來如下問題:
1、Dog d; v.push_back(&d); d是局部對象,離開範圍會自動銷毀,容器中的指標指向一堆垃圾。
2、為瞭解決上面的問題,使用 v.push_back(new Dog(d)); 這會帶來動態記憶體管理的負擔,考慮把v[j] 賦值給v[i],
3、v[j] = v[i]; 兩個指標指向同一個對象,v[j]和v[i] 不知道彼此,都不釋放,記憶體泄露,都釋放,行為未定義。
4、對v[i]做一個副本,由於不知道v[i]的真實類型,使用v[j] = new Animal(v[i]); 這又發生對象切割。
5、解決對象的切割,使用virtual clone方法,如下:v[j] = v[i].clone();
---------------------------------------------------------------------------------------------------------------------
使用代理類,對指標Animal* 封裝,棧上對象管理動態記憶體,實現指標的自動釋放。
如下:
AnimalProxy::AnimalProxy():_pa(NULL){}AnimalProxy::~AnimalProxy(){delete _pa;}// 注意:類中可以訪問自己的private成員,也可以訪問rhs的private成員AnimalProxy::AnimalProxy(const AnimalProxy& rhs){_pa = (rhs._pa == NULL ? rhs._pa->Clone():NULL);}AnimalProxy& AnimalProxy::operator=(const AnimalProxy& rhs){if(this != &rhs) // 等同測試{delete _pa; // delete NULL 也沒有問題_pa = (rhs._pa == NULL ? rhs._pa->Clone():NULL); // 指標為NULL判斷}return *this; // 返回引用}AnimalProxy::AnimalProxy(const Animal& animal):_pa(animal.Clone()){}
【C++沉思錄】代理類