前言:不同型別的物件,放進同一個容器,(下文以陣串列示容器)
代理類
問題:
現有不同種類的交通工具類派生層次,如下:

classVehicle{
public:
virtualdoubleweight()const=0;
virtualvoidstart()=0;
};
classAircraft:publicVehicle {
};
classAutomobile:publicVehicle {
};
我們想對一系列不同各類的Vehicle進行管理:
Vehicle parking_lot[1000];
不足:
抽象類不可實體化
若基類不是抽象類,型別轉換會帶來問題

經典解決方法:容器中存盤基類指標
Vehicle* parking_lot[1000];
Automobile x;
parking_lot[0] = &x;
不足:
記憶體管理的負擔
若容器中的指標在其它地方被釋放,會造成大量野指標
經典解決方法的改進:容器中的指標指向原物件的副本,
Vehicle* parking_lot[1000];
Automobile x;
parking_lot[0] =newAutomobile(x);
不足:
動態記憶體管理的負擔
需要知道物件x的靜態型別
再次改進:虛復制函式
classVehicle{
public:
virtualdoubleweight()const=0;
virtualvoidstart()=0;
virtualVehicle*copy()const=0;
virtual~Vehicle() {}
};
classAircraft:publicVehicle {
public:
Vehicle*copy()const{
returnnewAircraft(*this);
}
};
classAutomobile:publicVehicle {
public:
Vehicle*copy()const{
returnnewAutomobile(*this);
}
};
直接呼叫copy(),不需要知道x的靜態型別
Vehicle* parking_lot[1000];
Automobile x;
parking_lot[0] = x.copy();
引入代理類
我們引入代理類來避免顯式的記憶體分配,

一個Vehicle代理代表著一個繼承自Vehicle的物件,只要該代理關聯著該物件,該物件就一定存在,因此,復制該代理就會復制該物件,給代理賦新值也會先洗掉舊物件,再復制新物件,
classVehicleSurrogate{ public: VehicleSurrogate() : vp(0) {}// 注意這個預設構造,我們需要定義一個“空代理”的概念,類似零指標 VehicleSurrogate(constVehicle& v) : vp(v.copy()) {} VehicleSurrogate(constVehicleSurrogate& v) : vp(v.vp ? v.vp->copy() :0) {} VehicleSurrogate&operator=(constVehicleSurrogate& v) { if(this!= &v) { deletevp; vp = (v.vp ? v.vp->copy() :0); } return*this; } ~VehicleSurrogate() { deletevp; } doubleweight()const{ if(vp ==0) throw"vp == 0"; vp->weight(); } voidstart(){ if(vp ==0) throw"vp == 0"; vp->start(); } private: Vehicle* vp; };
需要注意的是,呼叫vp的成員函式前需要對vp進行判空,
如果你在學習C/C++的程序中遇到了問題,可以來加入小編的企鵝圈問小編哦~小編很熱情的(●’?’●)
現在我們管理一系列的Vehicle就方便多了:
VehicleSurrogate parking_lot[10];
Automobile x;
parking_lot[0] = x;
最后一行會呼叫VehicleSurrogate(const Vehicle& v)完成x從Automobile到VehicleSurrogate的型別轉換,而且會創建x的副本,
我們不需要考慮陣列中的副本釋放問題,VehicleSurrogate的解構式會幫我們做好,不同型別的物件,放進同一個容器,(下文以陣串列示容器)
代理類
問題:
現有不同種類的交通工具類派生層次,如下:
classVehicle{
public:
virtualdoubleweight()const=0;
virtualvoidstart()=0;
};
classAircraft:publicVehicle {
};
classAutomobile:publicVehicle {
};
我們想對一系列不同各類的Vehicle進行管理:
Vehicle parking_lot[1000];
不足:
抽象類不可實體化
若基類不是抽象類,型別轉換會帶來問題
經典解決方法:容器中存盤基類指標
Vehicle* parking_lot[1000];
Automobile x;
parking_lot[0] = &x;
不足:
記憶體管理的負擔
若容器中的指標在其它地方被釋放,會造成大量野指標
經典解決方法的改進:容器中的指標指向原物件的副本,
Vehicle* parking_lot[1000];
Automobile x;
parking_lot[0] =newAutomobile(x);
不足:
動態記憶體管理的負擔
需要知道物件x的靜態型別
再次改進:虛復制函式
classVehicle{
public:
virtualdoubleweight()const=0;
virtualvoidstart()=0;
virtualVehicle*copy()const=0;
virtual~Vehicle() {}
};
classAircraft:publicVehicle {
public:
Vehicle*copy()const{
returnnewAircraft(*this);
}
};
classAutomobile:publicVehicle {
public:
Vehicle*copy()const{
returnnewAutomobile(*this);
}
};
直接呼叫copy(),不需要知道x的靜態型別
Vehicle* parking_lot[1000];
Automobile x;
parking_lot[0] = x.copy();
引入代理類
我們引入代理類來避免顯式的記憶體分配,
一個Vehicle代理代表著一個繼承自Vehicle的物件,只要該代理關聯著該物件,該物件就一定存在,因此,復制該代理就會復制該物件,給代理賦新值也會先洗掉舊物件,再復制新物件,
classVehicleSurrogate{
public:
VehicleSurrogate() : vp(0) {}// 注意這個預設構造,我們需要定義一個“空代理”的概念,類似零指標
VehicleSurrogate(constVehicle& v) : vp(v.copy()) {}
VehicleSurrogate(constVehicleSurrogate& v) : vp(v.vp ? v.vp->copy() :0) {}
VehicleSurrogate&operator=(constVehicleSurrogate& v) {
if(this!= &v) {
deletevp;
vp = (v.vp ? v.vp->copy() :0);
}
return*this;
}
~VehicleSurrogate() {
deletevp;
}
doubleweight()const{
if(vp ==0)
throw"vp == 0";
vp->weight();
}
voidstart(){
if(vp ==0)
throw"vp == 0";
vp->start();
}
private:
Vehicle* vp;
};
需要注意的是,呼叫vp的成員函式前需要對vp進行判空,
現在我們管理一系列的Vehicle就方便多了:

VehicleSurrogate parking_lot[10];
Automobile x;
parking_lot[0] = x;
最后一行會呼叫VehicleSurrogate(const Vehicle& v)完成x從Automobile到VehicleSurrogate的型別轉換,而且會創建x的副本,
我們不需要考慮陣列中的副本釋放問題,VehicleSurrogate的解構式會幫我們做好,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/213715.html
標籤:C++
