毫不從新定義繼承而來的缺省參數值

考慮以下的代碼:函數

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;
    ...
};

class Circle: public Shape
{
public:
    virtual void draw(ShapeColor color) const;
    ...
};

以上代碼有個問題,若是你用下面的調用方式:spa

Shape *ps;
Shape *pc = new Circle;
Shape *pr = new Rectangle;

pc->draw(Shape::Red);    //Circle::draw(Shape::Red);
pr
->draw(Shape::Red);    //Rectangle::draw(Shape::Red); pr->draw();          //Rectangle::(Shape::Red)!!!!

咱們會發現,pr的動態類型是Rectangle*, 因此調用的是Rectangle的virtual函數,Rectangle::draw的缺省參數應該是GREEN,可是,因爲pr的靜態類型是Shape*,因此此調用的缺省參數值來自Shape而不是Rectangle。C++之因此這麼作,是考慮到運行時效率的問題。若是缺省參數值是動態綁定,編譯器就必須在運行期爲虛函數決定適當的缺省值。這比目前實行的「在編譯器決定」機制更慢更復雜。設計

那麼咱們怎麼作才適合呢?在派生類裏面也提供缺省值嗎?code

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;
    ...
};

Aha,代碼重複。blog

能夠用替代設計,好比能夠用基類的public 非虛函數調用private的虛函數,後者能夠被派生類從新定義,而讓非虛函數去作缺省參數的事情。繼承

class Shape
{
public:
    enum ShapeColor { Red, Green, Blue };
    void draw(ShapeColor color = Red) const         //non-virtual
    {
        doDraw(color);
    }
    ...
private:
    virtual void doDraw(ShapeColor color) const = 0;//do the real work
};

class Rectangle : public Shape
{
public:
    ...
private:
    virtual void doDraw(ShapeColor color) const;    //不須指定參數值
    ...
};

絕對不要從新定義一個繼承而來的缺省參數值,這些參數值都是靜態的,而虛函數倒是動態的。編譯器

相關文章
相關標籤/搜索