C++代理类的使用

这篇博客是我在学习C++沉思录的第5章做的笔记。

本文主要讲了C++中代理类的使用方法和使用情况。

 

所谓代理类,即surrogate.为什么要使用它呢,简单的举个例子.

 1 class Vehicle
2 {
3 public:
4 Vehicle(){}
5 virtual string getName()= 0;
6 }:
7
8 class Car : public Vehicle
9 {
10 public:
11 Car(){}
12 virtual string getName(){}
13 };
14
15 class Bike : public Bike
16 {
17 public:
18 Bike(){}
19 virtual string getName(){}
20 }:

有简单的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.

  1 /*
2 * =====================================================================================
3 *
4 * Filename: surrogate.cpp
5 *
6 * Description: chapter 5 in book
7 *
8 * Version: 1.0
9 * Created: 12/04/2011 07:04:12 AM
10 * Revision: none
11 * Compiler: gcc
12 *
13 * Author: summer (), marchtea213@gmail.com
14 * Company:
15 *
16 * =====================================================================================
17 */
18
19 /*
20 * =====================================================================================
21 * Class: Vehicle
22 * Description:
23 * =====================================================================================
24 */
25
26 #include <iostream>
27 #include <string>
28
29 using namespace std;
30
31 class Vehicle
32 {
33 public:
34
35 Vehicle(){}
36 virtual string getName() = 0;
37 virtual Vehicle* copy() const = 0;
38 virtual ~Vehicle(){} //虚析构函数是为了支持多态.但是本例中并不需要.
39 private:
40
41
42 };
43
44 class Car :public Vehicle
45 {
46 public:
47 Car(){}
48 virtual string getName() {return "car";}
49 virtual Vehicle* copy() const {return new Car;}
50 virtual ~Car(){}
51
52
53 };
54
55 class Bike : public Vehicle
56 {
57 public:
58 Bike(){}
59 virtual string getName(){return "bike";}
60 virtual Vehicle* copy()const {return new Bike;}
61 virtual ~Bike(){}
62 };
63
64 class VehicleSurrogate
65 {
66 public:
67 VehicleSurrogate():p(0){}
68 VehicleSurrogate(const Vehicle& v):p(v.copy()){}
69 VehicleSurrogate(const VehicleSurrogate &vs):p(vs.p ? vs.p->copy() : 0){}
70 VehicleSurrogate & operator=(const VehicleSurrogate &vs);
71 string getName(){return p->getName();}
72 ~VehicleSurrogate(){delete p;}
73 private:
74 Vehicle *p;
75 };
76
77 VehicleSurrogate & VehicleSurrogate::operator=(const VehicleSurrogate&vs)
78 {
79 if (this != &vs) //在删除p之前一定得记得判断vs和this是不是同一个,否则会有问题
80 {
81 delete p;
82 p = vs.p->copy();
83 }
84 return *this;
85 }
86
87
88
89 int main()
90 {
91 Car c;
92 Bike b;
93
94 VehicleSurrogate vs1(c);
95 std::cout << vs1.getName() << std::endl;
96 VehicleSurrogate vs2(b);
97 std::cout << vs2.getName() << std::endl;
98
99 return 0;
100
101 }

 

为此还改造了一下Vehicle,使其支持复制到我们的代理类中.

程序的运行结果也很清晰,正如我们预料的那样.分别是

car

bike.

 

代码很简单,不用解释也能看得清楚.

很明显,有了代理类之后,parkinglot也就不难定义了.

而通过这样的写法,也简化了我们在vector<Vehicle*>这种情况下的动态管理内存的麻烦.


后记:

       在看到代理类的优点的时候,我们也必须正视他的缺点.即每次使用都得要进行复制,如果对于某些特别大的类来说,复制并不是一个明智的选择.

       在接下来我会介绍handle类,解决了这个方面的问题.

posted @ 2011-12-04 01:22  marchtea  阅读(7835)  评论(3编辑  收藏  举报