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类,解决了这个方面的问题.

  • 相关阅读:
    利用DTrace实时检测MySQl
    改进MySQL Order By Rand()的低效率
    RDS for MySQL查询缓存 (Query Cache) 的设置和使用
    RDS For MySQL 字符集相关说明
    RDS for MySQL 通过 mysqlbinlog 查看 binlog 乱码
    RDS for MySQL Mysqldump 常见问题和处理
    RDS for MySQL Online DDL 使用
    RDS MySQL 表上 Metadata lock 的产生和处理
    RDS for MySQL 如何使用 Percona Toolkit
    北京已成为投融资诈骗重灾区:存好骗子公司黑名单,谨防上当!
  • 原文地址:https://www.cnblogs.com/marchtea/p/2275194.html
Copyright © 2011-2022 走看看