c++沉思錄中第5章代理類所述的代理類一個主要的特點是凡事都用複製。
首先說一下,c++沉思錄裏面對於句柄的設計思量,實現細節講的非常詳細,看c++primer理解句柄不是很透徹的可以拿這本書來看。用了三章的內容來講,第5章講代理類(類似句柄),第六章第七章講句柄。希望與大家共同討論這一個話題,如果你有實際應用的場合,希望你能與我分享。
class VehicleSurrogate
{
public:
VehicleSurrogate():vp(0){}
VehicleSurrogate(const Vehicle& v);
VehicleSurrogate(const VehicleSurrogate& v);
~VehicleSurrogate();
VehicleSurrogate& operator=(constVehicleSurrogate& v);
double weight() const;
void start();
private:
Vehicle* vp;
};
代理類中有指向所代理類族(一個類集合,他們是有繼承關係的多層)的一個對象的指針vp,
他的默認構造函數是把指針置空(NULL),
VehicleSurrogate():vp(0){}
接受Vehicle引用的構造函數,他能夠用copy虛函數複製一個Vehicle動態類型的對象,指定爲虛函數的原因爲,能夠保證複製的是Vehicle引用實際類型的副本。Vehicle類層次中基類把copy定義爲純虛函數,每一個子類都得定義copy函數,自動爲虛函數了。c++primer中此類函數命名爲clone,在沉思錄中起名copy,一個意思。
VehicleSurrogate(const Vehicle& v):
vp(v.copy()){};
同樣,有一個接受VehicleSurrogate常引用的構造函數,同樣是用了copy方法,只不過有了VehicleSurrogate來間接引用的。
VehicleSurrogate(constVehicleSurrogate& v):
vp(v.vp ? v.vp->copy(): 0){}
接下來是重載賦值操作符,賦值操作也一樣。
VehicleSurrogate&operator=(const VehicleSurrogate& v)
{
if(this != &v)
{
delete vp;
vp = (v.vp ? v.vp->copy():0);
}
return *this;
}
代理類代理的兩個原來類的函數。
double weight() const
{
if(!vp)
throw runtime_error("emptyVehicleSurrogate.weight()");
return vp->weight();
}
void start()
{
if(!vp)
throw runtime_error("emptyVehicleSurrogate.start()");
vp->start();
}
此處是代理類和句柄類的區別,代理類自己定義所代理類中的虛函數,在自己定義的函數中調用所代理類中的虛函數。而句柄類則是重載了箭頭操作和解引用操作來調用所代理類的成員的虛函數。但是,以上實現肯定是類似句柄類的值類型的實現了,因爲牽扯到複製和賦值時都是用copy實現了全部複製,並不是直接使用指針引用同一地址和計數。
完整的實現如下:
//vehicle.h
#include<iostream>
#include<stdexcept>
using std::runtime_error;
class Vehicle
{
public:
Vehicle(doublew, double v):weightn(w), velocity(v){}
virtualdouble weight() const = 0;
virtualvoid start() = 0;
virtual Vehicle* copy() const =0;
virtual~Vehicle(){}
protected:
doubleweightn;
doublevelocity;
};
class RoadVehicle: public Vehicle
{
public:
RoadVehicle(doublew, double v):Vehicle(w,v){}
RoadVehicle(constRoadVehicle &d):Vehicle(d.weightn, d.velocity)
{}
doubleweight() const
{
returnweightn;
}
voidstart()
{
velocity= 5;
}
RoadVehicle* copy() const
{
return newRoadVehicle(*this);
}
};
class AutoVehicle: publicRoadVehicle
{
public:
AutoVehicle(doublew, double v): RoadVehicle(w,v){}
doubleweight() const
{
returnweightn;
}
voidstart()
{
velocity= 5;
}
AutoVehicle* copy() const
{
return newAutoVehicle(*this);
}
};
class Aircraft: public Vehicle
{
public:
Aircraft(doublew, double v):Vehicle(w,v){}
doubleweight() const
{
returnweightn;
}
voidstart()
{
velocity= 5;
}
Aircraft* copy() const
{
return newAircraft(*this);
}
};
class Helicopter: public Aircraft
{
public:
Helicopter(doublew, double v):Aircraft(w,v){}
doubleweight() const
{
returnweightn;
}
voidstart()
{
velocity= 5;
}
Helicopter* copy()const
{
return newHelicopter(*this);
}
};
class VehicleSurrogate
{
public:
VehicleSurrogate():vp(0){}
VehicleSurrogate(constVehicle& v):
vp(v.copy()){}
VehicleSurrogate(constVehicleSurrogate& v):
vp(v.vp? v.vp->copy(): 0){}
~VehicleSurrogate()
{
deletevp;
}
VehicleSurrogate&operator=(const VehicleSurrogate& v)
{
if(this!= &v)
{
deletevp;
vp= (v.vp ? v.vp->copy(): 0);
}
return*this;
}
doubleweight() const
{
if(!vp)
throwruntime_error("empty VehicleSurrogate.weight()");
returnvp->weight();
}
voidstart()
{
if(!vp)
throwruntime_error("empty VehicleSurrogate.start()");
vp->start();
}
private:
Vehicle*vp;
};
//main.cpp
#include<iostream>
#include"vehicle.h"
using namespace std;
int num_vehicles;
int main(int argc, char *argv[])
{
VehicleSurrogate parking_lot[1000];
AutoVehicle x(5,10);
parking_lot[num_vehicles++] = x;
cout<<parking_lot[0].weight()<<endl;
}
注意:代碼中定義的copy函數返回指向本類的指針和返回基類指針是一樣的,反正實際類型爲本類指針。