代理类

问题引出:

处理跟踪一系列有内在联系的数据或对象时,容器往往是很好的办法,但容器对容器内的对象有一系列要求,比如可以复制,类型必须相同(本质是应该是数据大小相同,这样指针就可以按照一定的偏移量就行遍历)。

那么跟踪一系列不同种类的对象,该对象可以是位于一个完整继承层次中任何类的对象时,传统的方法就不好用。比如不同继承层次的对象大小就可能不一样,这样遍历的指针有可能出错;还有复制到容器时,子类就有可能为复制给父类而被阉割,这都是我们不想要的。但有时候确实需要放置一些多态类放到容器中便于管理。

经典的办法就是创建一存储目标对象指针的代理类,通过存储和操作代理类来达到间接操作目标对象的目的。

方法面对的问题:

为实现这方法需要处理几个问题:

  1. 怎么确定我们复制的对象类型。多态只有在运行时刻才能确定对象类型,编译时刻类型未知。这就导致一个问题:假设我们需要复制array[b]到array[a]我们该怎么复制?有以下两种方法:

    if(a != b){ 
    
    delete array[a]; 
    
    array[a] = array[b]; 
    
    }
    if(a != b){ 
    
    delete array[a]; 
    
    array[a] = new base-object(array[b]); 
    
    }
    第一种问题在于,两指针指向同一对象,容易造成指针悬挂。第二种问题在于不知道array[b]类型,这样复制会造成生成阉割的array[b]类型对象和本意不和。为处理复制编译时刻类型未知的对象问题,我们一般方法是使用虚复制函数,子类复制自己并返回。

  2. 控制内存分配的问题。子类复制自己并返回副本指针,代理类管理副本指针,必要时刻需要delete这段内存。

代码实现:

  1. 相关类:

    #ifndef STORAGE_VEHICLE_H 
    
    #define STORAGE_VEHICLE_H 
    
    
    #include <iostream> 
    
    using std::cout; 
    
    using std::endl; 
    
    //base class 
    
    class Vehicle { 
    
    public: 
    
    virtual void start() const {}; 
    
    virtual double weight() const {cout << "vehicle::weight" << endl;return 0;}; 
    
    
    virtual Vehicle* clone() const {return new Vehicle(*this);}; //虚复制函数 
    
    virtual ~Vehicle() {}; 
    
    }; 
    
    
    //derived class 
    
    class Car : public Vehicle { 
    
    public: 
    
    virtual double weight() const{ cout << "car::weight" << endl; return 0;} 
    
    
    virtual void start() const { cout << "car::start" << endl;} 
    
    
    virtual Vehicle* clone() const {return new Car(*this);} 
    
    
    virtual ~Car() {} 
    
    }; 
    
    
    class Bus : public Vehicle { 
    
    public: 
    
    virtual double weight() const { cout << "Bus::weight" << endl; return 0;} 
    
    
    virtual void start() const { cout << "Bus::start" << endl;} 
    
    
    virtual Vehicle* clone() const { return new Bus(*this);} 
    
    
    virtual ~Bus() {} 
    
    }; 
    
    #endif

  2. 代理类:

    #ifndef STORAGE_VEHICLE_SURROGATE_H 
    
    #define STORAGE_VEHICLE_SURROGATE_H 
    
    
    
    #include <iostream> 
    
    #include "vehicle.h" 
    
    using std::cout; 
    
    using std::endl; 
    
    
    class VehicleSurrogate { 
    
    public: 
    
    VehicleSurrogate() : vp(0) {}; 
    
    
    VehicleSurrogate(const VehicleSurrogate& v) : vp(v.vp ? v.vp->clone() : 0){}; 
    
    
    VehicleSurrogate(const Vehicle& v) : vp(v.clone()){}; 
    
    
    ~VehicleSurrogate() {if (!vp) delete vp;}; 
    
    
    VehicleSurrogate& operator=(const VehicleSurrogate& v){ 
    
    if (this != &v) 
    
    { 
    
    if (!vp) delete vp; 
    
    vp = (v.vp ? v.vp->clone() : 0); 
    
    } 
    
    return *this; 
    
    } 
    
    
    double weight() const { 
    
    if (vp == 0) 
    
    { 
    
    cout << "erro" << endl; 
    
    } 
    
    return vp->weight(); 
    
    } 
    
    
    void start() const { 
    
    if (vp == 0) 
    
    { 
    
    cout << "erro" << endl; 
    
    } 
    
    vp->start(); 
    
    } 
    
    
    private: 
    
    Vehicle* vp; 
    
    
    }; 
    
    #endif

  3. 测试:

    #include "stdafx.h"
    
    #include "vehicle.h"
    
    #include "vehicle_surrogate.h"
    
    #include <iostream> 
    
    using std::cout; 
    
    using std::endl; 
    
    
    
    int _tmain(int argc, _TCHAR* argv[]) 
    
    { 
    
    Car car1; 
    
    Bus bus1; 
    
    
    VehicleSurrogate vehsurr2[3] = {car1, bus1, car1};//虽说是写了car1等对象, 
    
    //但是后台是做了car-> VehicleSurrogate类的转换,所以VehicleSurrogate需要 
    
    //VehicleSurrogate(const Vehicle& v)构造函数 
    
    vehsurr2[0].weight(); 
    
    vehsurr2[1].weight(); 
    
    vehsurr2[2].weight(); 
    
    
    return 0; 
    
    }

    35845379

​这样一个完整的代理类就写好了。对象容器应用好像比较少,是不是可以应用于对象池什么的或是像设计模式中对大量类的管理?,具体案列没有见过。但是这种运用特定的资源类管理指针的思想到时很能启发人,比如smart point就是一个很好的应用。


PS:代理类对对象管理只涉及对象值管理,不涉及共享对象,因为有可能一个局部对象传了指针给容器,所以需要对象复制副本给代理类。

posted on 2013-05-23 23:14  X__XzZ  阅读(221)  评论(0编辑  收藏  举报

导航