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

//virtual是动态绑定( dynamically bound ), 而缺省数值却是静态绑定( statically bound )


/*******************************************
#include <string>
class Shape
{
public:
enum ShapeColor { Red, Green, Blue };
virtual void draw( ShapeColor color = Red ) const
{
std::cout<<"Shape::draw::"<<color<<std::endl;
}
};


class Rectangle : public Shape
{
public:
//赋于了不同的缺省参数值不好
virtual void draw( ShapeColor color = Green ) const
{
std::cout<<"Rectangle::draw::"<< color <<std::endl;
}
};


class Circle : public Shape
{
public:
virtual void draw( ShapeColor color ) const
{
std::cout<<"Circle::draw::"<< color <<std::endl;
}
//以上这么定,当客户以对象调用此函数时, 一定要指定参数值
//因为静态绑定下这个函数并不从其base继承缺省参数值
//但若以指针(或reference)调用此函数,可以不指定参数值
//因为动态绑定下这个函数会从其base继承缺省参数值
};


Shape* ps; //静态类型为Shape*,无动态类型
Shape* pr = new Rectangle(); //静态类型为Shape*,动态类型为Rectangle*
Shape* pc = new Circle(); //静态类型为Shape*,动态类型为Circle*
ps = pc; //动态类型变为Circle*
ps = pr; //动态类型变为Rectangle*
//不论它们真正指向什么,他们的静态类型都是Shape*
//virtual函数系动态绑定而来,意思是调用virtual函数时,究竟调用哪个函数由调用者的动态类型决定
**************************************************/


//如上,virtual函数由动态类型决定调用哪个,但是virtual函数的参数缺省值却是由静态类型决定
//为什么会如此设计:为了运行期效率。如果缺省参数是动态绑定,编译器就必须有某种办法为virtual函数决定适当的参数缺省值。
//这比目前的“在编译期决定”的机制更慢而且更复杂。为了执行速度和编译器实现上的简易度,做了如此取舍。


//问题:如果遵守规则,并同时提供相同的参数缺省值给Base和Derived类,那会发生什么呢?
//代码重复,并且代码重复带着相依性,如果Base的参数缺省值改了,那么要记得改所有的Derived的参数缺省值,这个不合理


/**解决办法之一: 使用NVI手法
class Shape
{
public:
void draw( ShapeColor color = Red ) const
{
doDraw(color);
}
private:
virtual doDraw( ShapeColor color ) const = 0;
};


class Rectangle : public Shape
{
public:
...
private:
virtual doDraw( ShapeColor color ) const;
};
********************************/

猜你喜欢

转载自blog.csdn.net/u010731020/article/details/81035993