zoukankan      html  css  js  c++  java
  • 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类,解决了这个方面的问题.

  • 相关阅读:
    CSS 仿 iOS 系统通知数字样式
    Asp.Net Grieview Eval 绑定数据 调用JS事件
    C#:decimal的去0显示
    WebService 错误:无法加载协定为xxx的终结点配置部分,因为找到了该协定的多个终结点配置
    C#:调用webservice时提示对操作的回复消息正文进行反序列化时出错
    C#:生成短网址
    C#:优惠券代码
    C# 调用webservice 几种办法(转载)
    ASP.NET: 正在中止线程 错误原及解决方法
    IOS:Safari不兼容Javascript中的Date问题
  • 原文地址:https://www.cnblogs.com/marchtea/p/2275194.html
Copyright © 2011-2022 走看看