条款37:绝不重新定义继承而来的缺省参数

在继承中,分为两类函数:virtual和non-virtual。而重新定义一个非虚函数是不好的(条款36),那么以下的讨论就是如何定义继承而来的虚函数。

强调:虚函数是动态绑定的,而缺省参数值是静态绑定的。

 1 #include <iostream>

 2 

 3 class Shape

 4 {

 5 public:

 6     enum ShapeColor{ Red, Green, Blue };

 7     virtual void draw(ShapeColor color = Red) const = 0;

 8 };

 9 

10 class Rectangle : public Shape

11 {

12 public:

13     virtual void draw(ShapeColor color = Green) const;  // 混淆设计:重新定义了继承而来的缺省参数值

14 };

15 void Rectangle::draw(ShapeColor color) const

16 {

17     std::cout << color << std::endl;

18 }

19 

20 class Circle : public Shape

21 {

22 public:

23     virtual void draw(ShapeColor color) const;  //

24 };

25 void Circle::draw(ShapeColor color) const

26 {

27     std::cout << color << std::endl;

28 }

29 

30 int main()

31 {

32     Shape* ps;                             // 静态类型为Shape*

33     Shape* pr = new Rectangle;         // 静态类型为Shape*

34     Shape* pc = new Circle;              // 静态类型为Shape*

35 

36     pr->draw();                            // 相当于调用了Rectangle::draw(Shape::Red)

37     pr->draw(Rectangle::Green);            // 调用Rectangle::draw(Rectangle::Green)

38     pc->draw(Circle::Blue);                // 调用Circle::draw(Circle::Blue)

39 

40     return 0;

41 }

42         

说明:

关于类型:ps、pr、pc不论其指向什么,静态类型都为Shape*。所谓动态类型,就是当前所指对象的类型,如,pr的动态类型是Rectangle*,pc的动态类型是Circle*,ps未指向任何对象,因此没有动态类型。

关于重定义缺省值:如上例中的pr->draw(),我们的本意可能是调用Rectangle::draw(Rectangle::Green),可实际上调用的是Rectangle::draw(Shape::Red),结果就是:调用的是派生类的函数,而使用的却是基类的默认参数,真是不伦不类。导致这种结果的原因就是:缺省参数值是静态绑定的,其总是根据pr的静态类型去寻找默认参数值,我们必须避免这种糟糕的设计。

 

你可能感兴趣的:(继承)