代理类
问题引出:
处理跟踪一系列有内在联系的数据或对象时,容器往往是很好的办法,但容器对容器内的对象有一系列要求,比如可以复制,类型必须相同(本质是应该是数据大小相同,这样指针就可以按照一定的偏移量就行遍历)。
那么跟踪一系列不同种类的对象,该对象可以是位于一个完整继承层次中任何类的对象时,传统的方法就不好用。比如不同继承层次的对象大小就可能不一样,这样遍历的指针有可能出错;还有复制到容器时,子类就有可能为复制给父类而被阉割,这都是我们不想要的。但有时候确实需要放置一些多态类放到容器中便于管理。
经典的办法就是创建一存储目标对象指针的代理类,通过存储和操作代理类来达到间接操作目标对象的目的。
方法面对的问题:
为实现这方法需要处理几个问题:
-
怎么确定我们复制的对象类型。多态只有在运行时刻才能确定对象类型,编译时刻类型未知。这就导致一个问题:假设我们需要复制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]); }
-
控制内存分配的问题。子类复制自己并返回副本指针,代理类管理副本指针,必要时刻需要delete这段内存。
代码实现:
-
相关类:
#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
-
代理类:
#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
-
测试:
#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; }
这样一个完整的代理类就写好了。对象容器应用好像比较少,是不是可以应用于对象池什么的或是像设计模式中对大量类的管理?,具体案列没有见过。但是这种运用特定的资源类管理指针的思想到时很能启发人,比如smart point就是一个很好的应用。
PS:代理类对对象管理只涉及对象值管理,不涉及共享对象,因为有可能一个局部对象传了指针给容器,所以需要对象复制副本给代理类。