原文 http://blog.csdn.net/kongying168/article/details/7220346
C++代理类的使用
所谓代理类,即surrogate.为什么要使用它呢,简单的举个例子.
class Vehicle
{
public:
Vehicle(){}
virtual string getName()= 0;
}:
class Car : public Vehicle
{
public:
Car(){}
virtual string getName(){}
};
class Bike : public Bike
{
public:
Bike(){}
virtual string getName(){}
}:
有简单的3个类,继承关系也很简单.
如果现在要定义个parkinglot.那该如何存呢?
有人会说,直接一个Vehicle数组就好了.即Vehicle parkinglot[500];
但是这里是会有很大错误的!
首先显然Vehicle是一个虚基类,虚基类是不会有对象的.
其次,这种数组的写法不能表现出任何多态的性质.(多态只能由指针和引用来体现)
还有一种写法就是vector<Vehicle*> parkinglot.
这种写法也是可以的.但是会有动态内存管理的麻烦.而且要是出现了如下的代码
void wrong_code(vector<Vehicle*> &parkinglot)
{
Car c;
parkinglot.push_back(&c);//将c插入到parkinglot内
}
int main()
{
vector<Vehicle*> parkinglot;
wrong_code(parkinglot);
parkinglot[0].getName(); //Oops!!parkinglot内存的地址指向了一块被销毁的内存
}
会造成程序运行的时候出现runtime error!
在这种大前提下,代理类就顺势而生了.
顾名思义,代理类就是指某个基类以及其子类的代理,其功能是使之能在容器中也表现出多态性.而没有动态内存管理的烦恼.
现在定义Vehicle以及子类的代理类VehicleSurrogate.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class Vehicle
{
public:
Vehicle(){}
virtual string getName() = 0;
virtual Vehicle* copy() const = 0;
virtual ~Vehicle(){} //虚析构函数是为了支持多态.但是本例中并不需要.
private:
};
class Car :public Vehicle
{
public:
Car(){}
virtual string getName() {return "car";}
virtual Vehicle* copy() const {return new Car;}
virtual ~Car(){}
};
class Bike : public Vehicle
{
public:
Bike(){}
virtual string getName(){return "bike";}
virtual Vehicle* copy()const {return new Bike;}
virtual ~Bike(){}
};
class VehicleSurrogate
{
public:
VehicleSurrogate():p(0){}
VehicleSurrogate(const Vehicle& v):p(v.copy()){}
VehicleSurrogate(const VehicleSurrogate &vs):p(vs.p ? vs.p->copy() : 0){}
VehicleSurrogate & operator=(const VehicleSurrogate &vs);
string getName(){return p->getName();}
~VehicleSurrogate(){delete p;}
private:
Vehicle *p;
};
VehicleSurrogate & VehicleSurrogate::operator=(const VehicleSurrogate&vs)
{
if (this != &vs) //在删除p之前一定得记得判断vs和this是不是同一个,否则会有问题
{
delete p;
p = vs.p->copy();
}
return *this;
}
int main()
{
Car c;
Bike b;
VehicleSurrogate vs1(c);
std::cout << vs1.getName() << std::endl;
VehicleSurrogate vs2(b);
std::cout << vs2.getName() << std::endl;
return 0;
}
为此还改造了一下Vehicle,使其支持复制到我们的代理类中.
程序的运行结果也很清晰,正如我们预料的那样.分别是
car
bike.
代码很简单,不用解释也能看得清楚.
很明显,有了代理类之后,parkinglot也就不难定义了.
而通过这样的写法,也简化了我们在vector<Vehicle*>这种情况下的动态管理内存的麻烦.
后记:
在看到代理类的优点的时候,我们也必须正视他的缺点.即每次使用都得要进行复制,如果对于某些特别大的类来说,复制并不是一个明智的选择.
在接下来我会介绍handle类,解决了这个方面的问题.