zoukankan      html  css  js  c++  java
  • 【C++沉思录】代理类

    1、考虑下面的场景:设计一个容器,包含一组类型不同但相互关联的对象(比如:Animal,Dog,Cat),对象具备多态行为。
    2、容器一般只能包含一种类型的对象,使用vector<Animal> 会造成对象切割,不具备多态行为。
    3、经典的解决办法是:vector<Animal*>, 但是这会增加内存管理的负担。考虑下面的情况:
    Dog d;
    vec[i] = &d; // 局部对象d销毁, vec[i] 指向垃圾

    vec[i] = vec[j]; // 指向同一个对象, 在vec析构之前,需要手动遍历vec,进行delete,两个delete同一个对象,行为未定义。
    4、怎么解决上面的问题,每次都创建一个新的对象。如下:
    Dog d;
    vec[i] = new Dog(d);

    vec[i] = new Animal(vec[j]); // 这里存在问题,由于vec[j] 类型未知,只能使用Animal,但是这造成对象切割。
    5、处理编译时类型未知的对象,使用虚方法。Animal 增加一个纯虚方法clone,纯虚方法导致Animal成为一个抽象类,
    不能实例化,同时要求子类必须重写clone方法。注:Animal 可以提供纯虚方法clone的实现。
    6、Animal* pa = new Dog; delete pa; 为了能够调用Dog的析构方法,定义Animal的析构方法是虚方法。注:多态行为要满足两个条件:
    方法是虚方法;表面类型和真实类型不一致。
    7、有没有更好的办法呢?
    使用代理类,对Animal* 管理。也就是栈上对象管理动态资源,利用C++的一个特性,栈上对象离开作用域,必定会调用析构方法,
    在析构方法中释放资源。
    8、代码如下:
    AnimalProxy::AnimalProxy():_pa(NULL)
    {

    }

    AnimalProxy::~AnimalProxy()
    {
    delete _pa;
    }

    // 注意:类中可以访问自己的private成员,也可以访问rhs的private成员
    AnimalProxy::AnimalProxy(const AnimalProxy& rhs)
    {
    _pa = (rhs._pa != NULL ? rhs._pa->Clone():NULL);
    }

    AnimalProxy& AnimalProxy::operator=(const AnimalProxy& rhs)
    {
    if(this != &rhs) // 等同测试
    {
    delete _pa; // delete NULL 也没有问题
    _pa = (rhs._pa != NULL ? rhs._pa->Clone():NULL); // 指针为NULL判断
    }
    return *this; // 返回引用
    }

    AnimalProxy::AnimalProxy(const Animal& animal):_pa(animal.Clone())
    {

    }

  • 相关阅读:
    Java异常的分类
    Java SE 6 新特性: Java DB 和 JDBC 4.0
    Java SE 6 新特性: 对脚本语言的支持
    面向对象开发方法优点
    RocketMQ之八:水平扩展及负载均衡详解
    Bluetooth 4.0之Android 解说
    iOS截取视频缩略图的两种方法
    Java NIO Buffer
    spark 启动job的流程分析
    C语言堆内存管理上出现的问题,内存泄露,野指针使用,非法释放指针
  • 原文地址:https://www.cnblogs.com/nzbbody/p/4678651.html
Copyright © 2011-2022 走看看