考虑如下的代码:
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; ... };
以上代码有个问题,如果你用下面的调用方式:
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++之所以这么做,是考虑到运行时效率的问题。如果缺省参数值是动态绑定,编译器就必须在运行期为虚函数决定适当的缺省值。这比目前实行的“在编译器决定”机制更慢更复杂。
那么我们怎么做才适合呢?在派生类里面也提供缺省值吗?
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,代码重复。
可以用替代设计,比如可以用基类的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; //不须指定参数值 ... };
绝对不要重新定义一个继承而来的缺省参数值,这些参数值都是静态的,而虚函数却是动态的。
时间: 2024-10-10 04:06:32