? 云南11选五走势图表:京东怎么看佣金 - ◆昨天云南十一选五开奖◆
  • 2017年度一级建造师考试成绩已发布 2019-03-19
  • 淮南选出54名代表出席省工会十四大 2019-03-19
  • 特朗普让俄重返G7遭5国反对 唯独安倍表态我理解 2019-03-14
  • 2018年军队院校报考指南 军校在山西省计划招生396人 2019-03-14
  • 你知道端午节的来历吗? 2019-03-13
  • 中外藏学专家齐聚西藏畅谈古象雄文化 2019-03-13
  • 自治区明确新生儿疾病筛查两项目价格 2019-03-07
  • 中美科学家在三峡地区发现世界最早动物足迹化石 2019-01-27
  • 百公里加速仅3.4s!宝马全新M5于3月22日上市 2018-12-12
  • 云南11选五走势图表:Cat cat

    昨天云南十一选五开奖 www.wahbn.com 小说:京东怎么看佣金作者:华杜辛扁更新时间:2019-03-23字数:92918

    “就是通信,不管多远都可以通话,嘟嘟……”一时语塞,看着李伯一脸茫然不知该如何解释才好。

    小鱼赚钱登录没有验证码

    “鸣人算了吧,你已经比起以前进步了很多,相信总有一天你会超越刘皓的,现在的刘皓太强了,据我所知他刚才根本没认真和你战斗,反而就是在嬉戏。
    “久闻林大人威名,如雷贯耳,今日一见果然英雄?!闭庑┎还强吞谆岸?,尤其是混在官场里的人,九成说的是鬼话,一成说的是人话已经算不错。

    实在是让人难以置信,可是他们却不得不相信,因为他们现在也享受到了和老子一样的待遇。

    怎样在一个容器中包含类型不同,但是彼此有关系的对象?众所周知,C++的容器只能存放类型相同的元素,所以直接在一个容器中存储不同类型的对象本身是不可能的,只能通过以下两种方案实现:

    1. 提供一个间接层,在容器中存放对象的指针而不是对象本身。

    2. 通过代理类实现。

    class Animal
    {
    public:
        virtual void Eat() = 0;
    };
    
    class Cat : public Animal{};
    class Dog : public Animal{};
    class Bird : public Animal{};

    在上面我们看到有一个虚基类和三个继承类,下面分别用两种方案来实现一个容器存放不同类型但又互相关联的类。

    1.通过指针实现

    Animal* animals_array[3];
    Cat cat;
    Dog dog;
    Bird bird;
    animals_array[0] = &cat;
    animals_array[1] = &dog;
    animals_array[2] = &bird;

    这样会带来一个问题,就是容器中的指针指向的对象如果被销毁,这个指针就会变成野指针,就像下面这样:

    Animal* animals_array[3];
    do
    {
        Cat cat;
        Dog dog;    
        Bird bird;
        animals_array[0] = &cat;
        animals_array[1] = &dog;
        animals_array[2] = &bird;
    }while(0);
    //此时对象已经被析构,容器中的指针指向未知内容

    也可以换一种方式,构造一个新的动态对象,将其地址放在容器中,这样就可以避免对象析构导致指针失效的问题:

    Cat cat;
    animals_array[0] = new Cat(cat);

    这样会曾加额外的内存开销,并且可能出现容器中两个指针同时指向一个对象的情况。
    所以,在容器中存放不同对象的指针并不是一个很好的解决方案。

    2.通过代理类实现

    实现代码如下:

    class Animal
    {
    public:
        virtual void Eat() = 0;
    
        //copy函数,构造一个基于自身对象类型的对象
        virtual Animal* copy() const = 0;
    
        virtual ~Animal() {}
    };
    
    class Cat : public Animal
    {
    public:
        virtual void Eat()
        {
            std::cout << "cat eat." << std::endl;
        }
    
        virtual Animal* copy() const
        {
            // 返回一个以自身作为参数构造的Cat类型的对象
            return new Cat(*this);
        }
    };
    
    class Dog : public Animal
    {
    public:
    
        virtual void Eat()
        {
            std::cout << "dog eat." << std::endl;
        }
    
        virtual Animal* copy() const
        {
            // 返回一个以自身作为参数构造的Dog类型的对象
            return new Dog(*this);
        }
    };
    
    class Bird : public Animal
    {
    public:
    
        virtual void Eat()
        {
            std::cout << "bird eat." << std::endl;
        }
    
        virtual Animal* copy() const
        {
            // 返回一个以自身作为参数构造的Bird类型的对象
            return new Bird(*this);
        }
    };
    
    //代理类
    class AnimalSurrogate
    {
    public:
        AnimalSurrogate() :pa(NULL) {}
    
        AnimalSurrogate(const Animal& ani)
        {
            pa = ani.copy();
        }
    
        //拷贝构造
        AnimalSurrogate(const AnimalSurrogate& ani_srg)
        {
            pa = ani_srg.pa != nullptr ? ani_srg.pa->copy() : nullptr;
        }
    
        ~AnimalSurrogate()
        {
            if (pa != nullptr)
            {
                delete pa;
                pa = nullptr;
            }
        }
    
        //重载 = 操作符
        AnimalSurrogate& operator=(const AnimalSurrogate& ani_srg)
        {
            if (this != &ani_srg)
            {
                delete pa;
                pa = ani_srg.pa != nullptr ? ani_srg.pa->copy() : nullptr;
            }
            return *this;
        }
    
        //将基类中的公共函数搬过来,这样就可以通过代理类直接访问这些方法
        void Eat()
        {
            if (pa == nullptr)
            {
                throw "empty AnimalSurrogate.Eat()";
            }
            return pa->Eat();
        }
    
    private:
        Animal* pa;//存储基类的指针
    };

    通过代码可以看出来,所谓的代理类,就是构造一个新的类,这个类中包含关联的基类类型的指针,该指针可以指向不同类型但又相互关联的子类对象,通过指针可以转调对象的方法,同时实现内存的管理。代理类的实用方法如下:

    Cat cat;
    Dog dog;
    Bird bird;
    
    arr[0] = AnimalSurrogate(cat);
    arr[1] = AnimalSurrogate(dog);
    arr[2] = AnimalSurrogate(bird);
    
    arr[0].Eat();//输出 cat eat.
    arr[1].Eat();//输出 dog eat.
    arr[2].Eat();//输出 bird eat.

    总结:代理类的的每个对象都代表另一个对象,该对象可以使位于一个完成继承层次中的任何类的对象。通过在容器中用代理对象而不是对象本身的方式,实现容器中存放不同类型的对象。

    使用代理类的优缺点如下:

    • 优点:使用代理类比直接在容器中存放不同对象的指针更安全,便于实现内存管理。
    • 缺点:内存开销太大,放入容器的每个对象都需要拷贝一次,不够灵活。

    为了避免对象的拷贝,可以通过句柄类来实现,关于句柄类的原理和使用在下一篇问文章中作介绍。

    编辑:北开

    发布:2019-03-23 02:08:39

    当前文章://www.wahbn.com/blxhv/19800.html

    安卓手赚宝?? 淘宝客推广付费比例最高多少 保险家园直通车靠谱吗 去哪里找APP推广 南宁农院路附近有什么兼职可以做? 上来要淘宝产品推广服务费 赚生活平台怎么样 手机游戏最赚人民币

    53647 33154 82177 39534 57240 2315612175 29257 99250

    我要说两句: (0人参与)

    发布
  • 2017年度一级建造师考试成绩已发布 2019-03-19
  • 淮南选出54名代表出席省工会十四大 2019-03-19
  • 特朗普让俄重返G7遭5国反对 唯独安倍表态我理解 2019-03-14
  • 2018年军队院校报考指南 军校在山西省计划招生396人 2019-03-14
  • 你知道端午节的来历吗? 2019-03-13
  • 中外藏学专家齐聚西藏畅谈古象雄文化 2019-03-13
  • 自治区明确新生儿疾病筛查两项目价格 2019-03-07
  • 中美科学家在三峡地区发现世界最早动物足迹化石 2019-01-27
  • 百公里加速仅3.4s!宝马全新M5于3月22日上市 2018-12-12