考慮以下的代碼:函數
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; //不須指定參數值 ... };
絕對不要從新定義一個繼承而來的缺省參數值,這些參數值都是靜態的,而虛函數倒是動態的。編譯器