effective c++ 第六章
2011-08-07 20:33 Clingingboy 阅读(305) 评论(0) 收藏 举报
条款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...
                    
                
                
            
        
浙公网安备 33010602011771号