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

1、绝不重新定义继承而来的缺省参数值所牵涉的范围?

继承的函数分为两种:non-virtualvirtual。而non-virtual函数是完全不能重新定义的(函数体、缺省参数都不可以),因此我们所说的绝不重新定义继承而来的缺省参数值实际指的是virtual函数。

2、为什么不能重新定义继承而来的缺省参数值?

因为virtual 函数体是动态绑定的,但是virtual 函数的缺省参数是静态绑定的。假如通过指针或者引用访问重新定义继承而来的virtual函数的缺省参数值,则会造成错误。(例如:函数体为派生类版本,但是缺省参数却是基类版本。)

注意:C++编译器将 virtual函数体设为动态的,而将virtual的缺省参数设为静态的是出于效率的考虑。如果缺省参数设为动态的,程序运行机制会变得更慢、更复杂。

3、何谓静态绑定和动态绑定?

  • 静态绑定,又叫前期绑定。
    对象的静态类型,就是它在程序中被声明时所采用的类型。

  • 动态绑定又叫后期绑定。

  • 对象的动态类型指的是指针(或引用)目前所指对象的类型。动态类型可以表现出一个对象将会有什么行为。动态类型可以在执行过程中被改变。

举例:

在这里插入图片描述

//ps、pc、pr 的静态类型为 Shape*
     Shape* ps;						//ps 动态类型:无
     Shape* pc = new Circle;		//pc动态类型:圆形
     Shape* pr = new Rectangle;		//pr动态类型: 矩形
	
	 ps = pc;						
	 ps = pr;						//动态类型可以在运行期间改变。

4、在遵守该规则的前提下,如何做到同时给base classderived class 提供缺省参数?

方案一:一般手法,基类和所有派生类提供一模一样的缺省参数。
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 = Red) const;
    ...
};

代码的缺点:

  • 重复度大。(每个派生类都要指定缺省参数ShapeColor color等于Red )
  • 灵活性差。(当基类的缺省参数改变时,所有派生类的缺省参数也要跟着修改。)
方案二:NVI手法替代方案
class Shape {
public:
    enum ShapeColor {Red, Green, Blue};
    void draw(ShapeColor color = Red) const            //如今它是non-virtual
    {
        doDraw(color);                                 //调用一个virtual
    }
    ...
private:
    virtual void doDraw(ShapeColor color) const = 0;    //真正的工作在此处完成
};

class Rectangle: public Shape{
public:
    ...
private:
    virtual void doDraw(ShapeColor color) const;        //注意,无须指定缺省参数值。
    ...
};


Shape * rec = new Rectangle();
rec->draw();			//  缺省参数调用,缺省参数为Red  矩形版本draw()
rec->draw(Green);		//  带参数调用					 矩形版本draw()

优点:

  • 基类缺省发生改变,派生类不需要修改参数。
posted @ 2019-12-24 10:34  江南又一春  阅读(192)  评论(0编辑  收藏  举报