条款37:绝不重新定义继承而来的 缺省参数值
在继承一个virtual函数的时候,如果这个virtual函数同样是有默认值的话,那么其表明这次继承既存在动态绑定也存在静态绑定:例如下面这个例子:
1 class Shape{ 2 public: 3 enum shapeColor{red, green, blue}; 4 virtual void draw(shapeColor color = red)const = 0; 5 //注意,这里的颜色是静态绑定的 6 }; 7 class Recantagle : public Shape{ 8 public: 9 void draw(shapeColor color = green)const; 10 //但是这里的默认参数!!! 11 }; 12 class Circle : public Shape{ 13 public: 14 void draw(shapeColor color) const; 15 };
这里就出现问题了,当使用一个Shape指针调用虚函数draw的时候,像下面这样:
Shape * sp = new Revantagle();
sp->draw();
对于这个draw函数来说,结果害死没问题的,起执行的肯定还是动态绑定,但是对于draw的默认参数就会有问题了,其执行的将会是基类中的参数red,因为对于他只能执行静态绑定。
即使在base class与derived class中提供相同的静态对象的默认初始值,那么情况也不好,这样造成的是base class 与derived class的代码相互依赖
解决这个的一般办法是:使用所谓的non-virtual interface手法:
1 class Shape{ 2 public: 3 enum shapeColor{red, green, blue}; 4 void draw(shapeColor & color = red) const { 5 doDraw(color); 6 } 7 private://注意这里是private 8 virtual void doDraw(shapeColor & )const = 0; 9 }; 10 class Recantagle : public Shape{ 11 public: 12 //直接继承基类的public函数即可 13 private: 14 void doDraw(shapeColor & ) const; 15 };
这样的就实现了同上面一样的效果。
小结:绝对不要去定义一个继承而来的缺省的参数值,即使继承到的是相同的参数值也不可行,virtual函数确是唯一应该被复写的东西