代理类(Surrogate)

      依然是学习<Ruminations On c++>的一点笔记。

问题的提出是:怎样设计一个C++容器,使它有能力包含类型不同而彼此相关的对象呢?

容器通常只能包含一种类型的对象,所以很难在容器中存储对象本身,最容易想到的就是存储指针(我目前在项目中使用的也是这种方法),这样虽然可以通过继承来处理类型不同的问题,但是也增加了内存分配的额外负担。

书中介绍了一种叫做代理的对象来解决这个问题,代理类是句柄类中最简单的一种,下面是一个简单的代理类实现:

// Surrogate.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#include <iostream>
#include <vector>
using namespace std;

class Vehicle
{
public:
virtual double weight()const =0;
virtual void   start()=0;
virtual Vehicle* copy()const=0;//用来复制编译时类型未知的对象
virtual ~Vehicle()//以便调用正确的派生类析构函数
{

}
//...
};

class RoadVehicle : public Vehicle
{
public:
double weight()const
{
cout<<"RoadVehicle::weight()"<<endl;
return 0;
}
void   start()
{
cout<<"RoadVehicle::start()"<<endl;
}
Vehicle* copy()const
{
return new RoadVehicle(*this);
}
/**/
};

class AutoVehicle : public RoadVehicle
{
public:
double weight()const
{
cout<<"AutoVehicle::weight()"<<endl;
return 0;
}
void   start()
{
cout<<"AutoVehicle::start()"<<endl;
}
Vehicle* copy()const
{
return new AutoVehicle(*this);
}
/**/
};

class Aircraft : public Vehicle
{
public:
double weight()const
{
cout<<"Aircraft::weight()"<<endl;
return 0;
}
void   start()
{
cout<<"Aircraft::start()"<<endl;
}
Vehicle* copy()const
{
return new Aircraft(*this);
}
/**/
};

class Helicopter : public Aircraft
{
public:
double weight()const
{
cout<<"Helicopter::weight()"<<endl;
return 0;
}
void   start()
{
cout<<"Helicopter::start()"<<endl;
}
Vehicle* copy()const
{
return new Helicopter(*this);
}
/**/
};

//代理类
class VehicleSurrogate
{
public:
VehicleSurrogate();
VehicleSurrogate(const Vehicle&);
~VehicleSurrogate();
VehicleSurrogate(const VehicleSurrogate&);
VehicleSurrogate& operator=(const VehicleSurrogate&);

//来自类Vehicle的操作
double weight()const;
void start();
private:
Vehicle *vp;
};

VehicleSurrogate::VehicleSurrogate():vp(0)
{

}

VehicleSurrogate::VehicleSurrogate(const Vehicle& v):vp(v.copy())
{

}

VehicleSurrogate::~VehicleSurrogate()
{
delete vp;
}

VehicleSurrogate::VehicleSurrogate(const VehicleSurrogate& v):vp(v.vp?v.vp->copy():0)
{

}

VehicleSurrogate& VehicleSurrogate::operator=(const VehicleSurrogate& v)
{
if (this!=&v)
{
delete vp;
vp=(v.vp?v.vp->copy() : 0);
}
return *this;
}

//直接转发给vp调用
double VehicleSurrogate::weight()const
{
if (vp==0)
{
throw "empty VehicleSurrogate.weight()";
}
return vp->weight();
}

void VehicleSurrogate::start()
{
if (vp==0)
{
throw "empty VehicleSurrogate.start()";
}
vp->start();
}

int _tmain(int argc, _TCHAR* argv[])
{
vector<VehicleSurrogate> vecVS;

RoadVehicle rv;
Aircraft ar;
AutoVehicle av;
Helicopter hc;
vecVS.push_back(rv);
vecVS.push_back(ar);
vecVS.push_back(av);
vecVS.push_back(hc);

vector<VehicleSurrogate>::iterator iter=vecVS.begin();
vector<VehicleSurrogate>::iterator iterEnd=vecVS.end();
while(iter!=iterEnd)
{
iter->weight();
iter->start();
iter++;
}

_CrtDumpMemoryLeaks();

return 0;
}

下面是测试结果,使用VS2005发现有内存泄漏,暂时没找到原因。

result