• effective c++ 第六章


    条款32:确定你的public继承塑模出is-a关系

    确认子类和父类的关系是正确的

    class Person {...};
    
    class Student: public Person {...};
    

    以下有问题

    class Bird {
    
     public:
    
         virtual void fly();                  // birds can fly
         ...
    
     };
    
     class Penguin:public Bird {            // penguins are birds
         ...
     };
    

    属于设计问题,以上可以把fly声明为虚方法,然后在Penguin报error都可以

    条款33:避免遮掩继承而来的名称

    下列代码出现遮掩问题

    class Base {
    private:
        int x;
    public:
        virtual void mf1() = 0;
        virtual void mf1(int);
        virtual void mf2();
        void mf3();
    
        void mf3(double);
        ...
    
    };
    
    class Derived: public Base {
    
    public:
        virtual void mf1();
        void mf3();
        void mf4();
    
        ...
    
    };
    

    使用示例

     Derived d;
     int x;
     ...
    d.mf1();                   // fine, calls Derived::mf1
    d.mf1(x);                  // error! Derived::mf1 hides Base::mf1
    d.mf2();                   // fine, calls Base::mf2
    d.mf3();                   // fine, calls Derived::mf3
    d.mf3(x);                  // error! Derived::mf3 hides Base::mf3
    

    要想在子类使用父类被遮掩的方法可以用using关键字,以下使得上面的代码正常运行

    class Derived: public Base {
    public:
        using Base::mf1;       // make all things in Base named mf1 and mf3
        using Base::mf3;       // visible (and public) in Derived's scope
        virtual void mf1();
        void mf3();
        void mf4();
        ...
    };
    

    使用private隐藏基类函数,只允许在子类调用

    class Derived: private Base {
     public:
         virtual void mf1()                   // forwarding function; implicitly
         { Base::mf1(); }                     // inline (see Item30)
             ...
    };
    ...
    Derived d;
    int x;
    d.mf1();                               // fine, calls Derived::mf1
    d.mf1(x);                              // error! Base::mf1() is hidden
    

    条款34:区分接口继承和实现继承

    class Shape {
    
    public:
    
        virtual void draw() const = 0;
        virtual void error(const std::string& msg);
        int objectID() const;
        ...
    
    };
    

    抽象方法必须实现即接口继承,具备抽象方法的类(抽象类)无法直接实例化 (虚方法)实现方法子类可以选择不实现

    条款35:考虑virtual函数以外的其他选择

    1.模板模式,重写部分函数

    class GameCharacter {
    public:
        int healthValue() const               // derived classes do not redefine
    
        {                                     // this — see Item 36
            ...                                 // do "before" stuff — see below
                int retVal = doHealthValue();       // do the real work
            ...                                 // do "after" stuff — see below
                return retVal;
        }
        ...
    private:
    
        virtual int doHealthValue() const     // derived classes may redefine this
        {
            ...                                 // default algorithm for calculating
        }                                     // character's health
    };
    

    2.策略模式

     class GameLevel {
    
     public:
    
         float health(const GameCharacter&) const;      // health calculation
    
         ...                                            // mem function; note
    
     };                                               // non-int return type
    
     class EvilBadGuy: public GameCharacter {         // as before
    
         ...
    
     };
    
     class EyeCandyCharacter:   public GameCharacter {  // another character
    
         ...                                              // type; assume same
    
     };                                                 // constructor as
    

    条款36:绝不重新定义继承而来的non-virtual函数

    同条款33,必须去这么做

    class B {
    public:
        void mf();
        ...
    
    };
    
    class D: public B { 
    public:
        void mf();
        ... 
    };
    

    条款37:绝不重新定义继承而来的缺省参数值

    以下子类重写的缺省参数值将会无效(静态绑定,为了运行效率)

    // a class for geometric shapes
    class Shape {
    public:
        enum ShapeColor { Red, Green, Blue };
        // all shapes must offer a function to draw themselves
        virtual void draw(ShapeColor color = Red) const = 0;
        ...
    
    };
    
    class Rectangle: public Shape {
    public:
    
        // notice the different default parameter value — bad!
        virtual void draw(ShapeColor color = Green) const;
        ...
    };
    

    条款38:通过复合塑模出has-a或”根据某物实现出”

    不通过继承的方式,而是通过复合和适配的方式,实现功能,避免继承父类的耦合度,优先采用此方案

    class Address { ... };             // where someone lives
    
    class PhoneNumber { ... };
    
    class Person {
    public:
        ...
    private:
    
        std::string name;               // composed object
    
        Address address;                // ditto
    
        PhoneNumber voiceNumber;        // ditto
    
        PhoneNumber faxNumber;          // ditto
    
    };
    

    用list实现Set

    template<class T>                   // the right way to use list for Set
    class Set {
    public:
        bool member(const T& item) const;
        void insert(const T& item);
        void remove(const T& item);
        std::size_t size() const;
    private:
        std::list<T> rep;                 // representation for Set data
    };
    

    条款39:明智而审慎地使用private继承

    private继承意味着implemented-in-terms-of(根据某物实现出)。用意是为了采用基类已经备妥的某些特性

    条款40:明智而审慎地使用多重继承

    1.函数重名调用

     class BorrowableItem {             // something a library lets you borrow
    
     public:
    
         void checkOut();                 // check the item out from the library
         ...
     };
    
     class ElectronicGadget {
    
     private:
    
         bool checkOut() const;           // perform self-test, return whether
         ...                              // test succeeds
     };
    
     class MP3Player:                   // note MI here
    
         public BorrowableItem,           // (some libraries loan MP3 players)
    
         public ElectronicGadget
    
     { ... };                           // class definition is unimportant
    
     MP3Player mp;
    
    mp.checkOut();                     //wrong ambiguous! which checkOut?
    mp.BorrowableItem::checkOut();              // ah, that checkOut...
    
  • 相关阅读:
    jquery设置控件位置的方法
    Redis学习(1)——下载与配置[转]
    Redis中redis.conf里面配置详解
    JAVA 上加密算法的实现用例,MessageDigest介绍
    JAVA的StringBuffer类[转]
    java synchronized详解[转]
    windows命令行下批量拷贝同一后缀的文件到另外一个目录
    批处理for命令详解(转)
    myeclipse10.X以上的破解方法
    jquery的get()方法
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/2130237.html
Copyright © 2020-2023  润新知