zoukankan      html  css  js  c++  java
  • effective c++ 笔记 (35-40)

    //---------------------------15/04/24----------------------------

    //#35   考虑virtual函数以外的其他选择

    {

    /*

        1:通常情况下对于有变动的东西,我们都会设计成virtual函数,然后由子类来继承,并重新实现,

          但是,由于这个惯性思维,成了弱点。因为我们这样就没有想过别的实现方法。

        2:Non-Virtual Interface来代替virtual函数。

            1>virtual函数设计成private,并使用别的public函数调用。这里有一个很关键的一点:

              private virtual函数能实现多态么?答案是肯定的。尽情地重定义吧。

            2>在调用virtual函数的前后可以加上一些自己的控制,比如上锁,记录等等一切你想做的。

            3>其实也不一定必须是private的,自己看情况定义吧。

        3:使用Strategy模式:

            1>当你需要virtual函数时,可以考虑存储一个仿函数对象,然后在一个public函数中调用这个

              仿函数。

            2>这个仿函数内部的操作不应该依赖于类的内部细节,不然还是乖乖用virtual函数来的好。

            3>这时你会发现,可以动态地改变要调用的函数,比如一个计算血量值的函数,可以一开始调用

              正常版本的,当角色中毒什么的,就换一个计算血量的函数。哇!cool

        

    */

    }


    //#36   绝不重新定义继承而来的non-virtual函数

    {

    /*

        前提:D public继承自 B

        先看两个准则(前面的条款已经将过的)

            1>适用于B对象的每一件事,也使用于D对象,因为每个D对象 isa B对象。

            2>D一定会继承Bnon-virtual函数的接口和实现。

        所以,如果我们重新定义了一个non-virtual函数:

            1>Dpublic方式继承B,那么当D有一个函数需要重新定义(不变性凌驾特异性),这个函数

              应该为virtual的而不是non-virtual的。

            2>如果这个函数不需要被重定义(特异性凌驾不变性),那么D久不需要重定义mf,而且它也

              不应该尝试这么做。

        所以结论是:不要重定义继承而来的non-virtual函数。

     

    */

    }


    //#37   绝不重定义继承而来的缺省参数值

    {


    //  1:看下这两个函数:

        class Shape

        {

        public:

            enum ShapeColor{Red, Green, Blue};

            virtual void draw(ShapeColor color = Red) const = 0;

        };

        class Rectangle : public Shape

        {

        public:

            virtual void draw(ShapeColor color = Green) const;

        };

    /*

            这么做的结果就是:当客户使用基类指针,子类对象时,调用的内容是子类的,默认参数确实基类的。

            这样子做没有意义,所以问题朝着两个方向发展:

                1>你想切换默认参数。

                2>你想保留默认参数,但是切换调用的内容。如果子类也要使用相同的参数,那么如果默认参数一改变

                  基类和子类的都必须改变,所以这很糟糕。

            实现起来很简单嘛:

                1>想切换参数?定义一个non-virtual函数,然后用virtual的函数调用之,

                  调用时传入不同的参数就ok了。

                2>想切换调用内容?定义一个private virtual函数,然后用带着默认参数的non-virtual函数调用之。

     

    */

    }


    //#38   通过复合塑膜出has-a"根据某物实现出"

    {

    /*

        复合有两种情况:

            1>has-a

                如果你塑造的对象是世界中的某些事物,比如人、物、汽车等等,那么这样的对象属于应用域,

                当复合发生在应用域时,表现出has-a的关系。

            2>is-implemented-in-terms-of(根据某物实现出)

                如果你塑造的对象是为了实现细节上的人工制品,像缓冲区、互斥锁等,这样的对象属于实现域

                这样的复合表现出is-implemented-in-terms-of关系。

                具体的例子就是,当你想要实现一个set时,你可能需要在类内含一个std::list,因为你不想

                自己写list,这样的关系就是is-implemented-in-terms-of,这个set是根据list实现的

                这里不用继承的原因是:set不是一个listlist能用的地方set不一定能用。比如list可以插入

                重复的值而set不行。

    */

    }


    //#39   明智而审慎地使用private继承

    {

    /*

        1:private继承意味着is-implemented-in-terms-of。也就是和复合有着异曲同工之妙,然而哪个更好呢?

            1>复合可以防止virtual函数被重定义。

            2>复合可以解耦两个类,减少编译依赖性。

            3>private继承可以实现EBO,也就是使一个空的基类真的不占内存。

            4>private可以访问到基类protected的内容,复合不行。

        2:最后得出的结论:

            1>首先考虑复合。

            2>真的无法用复合实现,或者真的看重那4byte的字节,那就换成private吧。

    */

    }


    //#40   明智而审慎地使用多重继承

    {

    /*

        1:多继承常常有很多缺点:

            1>比单一继承复杂,可能会造成歧义性,也就是继承的两个基类中有相同名字的函数,那么单单使用

              函数名是不知道调用哪一个的。

            2>要求基类都来自virtual继承,可是virtual继承是以增加体积,减慢速度,以及复杂的初始化

              为成本实现的如果virtual base classes不带任何数据,将是最具使用价值的情况。

              (ps:都不带数据了,我不是virtual继承有影响么?就算不是virtual继承也不会有重复东西了啊,

              最多就是一个virtual指针)

        2:多重继承正当的用途:设计模式中的适配器模式

            但是这也是可以转变为复合方式来实现的,所以你需要明智而审慎地决定是否适用多重继承(ps:不建议使用)

    */

    }


  • 相关阅读:
    JavaEE——SpringMVC(11)--拦截器
    JavaEE——SpringMVC(10)--文件上传 CommonsMultipartResovler
    codeforces 460A Vasya and Socks 解题报告
    hdu 1541 Stars 解题报告
    hdu 1166 敌兵布阵 解题报告
    poj 2771 Guardian of Decency 解题报告
    hdu 1514 Free Candies 解题报告
    poj 3020 Antenna Placement 解题报告
    BestCoder5 1001 Poor Hanamichi(hdu 4956) 解题报告
    poj 1325 Machine Schedule 解题报告
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983126.html
Copyright © 2011-2022 走看看