c++ 沉思录---代理类

一、问题

  如何设计一容器能包含彼此不同而又相互关联的类的对象(处于完整的继承层次的类)?因为一般的数组容器都只能包含一种类型的对象。  

  假设有一个表示不同类型的交通工具的类的派生层次:    

class Vehicle
{
public:
    virtual double weight () const = 0;
    virtual void start() = 0;
    //.....
};

class RoadVehicle : public Vehicle
{
public:
    /* data */
};

class AutoVehivle : public Vehicle
{
public:
    /* data */
};

class Aircraft : public Vehicle
{
public:
    /* data */
};

  现在我们需要一个容器,这里使用数组表示,能够包含所有上述类的对象,Vehicle parkint_lot[100]; 这样肯定不对

    错误原因:1. Vehicle 是个抽象基类(含有纯虚函数),不能实例化对象

      2. 假设Vehicle能够实例化也不对,Parking_lot[num_vehicles++] = 派生类对象,这样的操作,会将派生类对象转化为一个Vehicle类的对象,会丢失所有Vehicle类中没有的成员。最后的结果是Parking_lot是Vehicle的集合。

二、解决方案1(传统的解决方法)

   通过在数组中存储基类的指针,因为基类的指针转换为派生类的指针是容易且安全的。

   Vehicle*  Parking_lot[100];

    然后输入类似:

    Automonbile x =

     1: Parking_lot[num_vehicles++] = &x;  

     存在问题:如果x是局部变量,一旦变量x销毁了,Parking_lot 就不知道指向什么东西了。

     2:  Parking_lot[num_vehicles++] =  new Automobile(x);

    存在问题:为了解决1中问题,改用存储对象副本的指针。这种方法会带来一定的内存管理负担,其实我觉得还行,没那么严重,在需求没那么严格的情况下这种方法还是可以使用的。

 但是,这种只有当我们确定知道要放入parking_lot对象的静态类型后,才启作用!!!

 注意:用基类的指针或引用引用一个派生类对象时,由于派生类对象也是基类的对象,所以这样也是安全的但是只能引用基类中所拥有的成员,不能引用在派生类中定义的成员,否则编译器会报错。

三、解决方案2(代理类)

  代理类:定义一个行为和Vehicle对象相似,而又潜在的表示为所有继承自Vehicle类的对象的东西,我们把这种类的对象称之为代理。

  在Vehicle类中添加虚复制函数

  virtual Vehicle* copy() const = 0;

  派生类中实现:  

  Vehicle*  派生类名称::copy() const{

    return new 派生类名称(*this);

  }

class VehicleSurrogate
{
public:
    VehicleSurrogate();
    ~VehicleSurrogate();
    VehicleSurrogate(const Vehicle& v){
        vp(v.copy());
    }

    VehicleSurrogate(const VehicleSurrogate&);
    VehicleSurrogate& operator = (const VehicleSurrogate&);
private:
    Vehicle* vp;
};

 代理类的成员变量为Vehivle 类型的指针,参数为const Vehicle& 类型的构造函数,可以为任意继承自Vehicle的类的对象创建代理。

使用方法:

VehicleSurrogate paking_lot[100];

Automobile x;

Paking_lot[num_vehicles++] = x;   等价于 paking_lot[num_vehicles++] = VehicleSurrogate(x);

 

posted @ 2015-12-04 00:06  wxquare  阅读(430)  评论(0编辑  收藏  举报