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

  • 条款36说明了重新定义一个继承而来的non-virtual函数永远是错误的,所以本条款的理由就是virtual函数系动态绑定,而缺省参数值确实静态绑定
    考虑如下代码:
// 一个用于描述几何形状的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 = Green) const;
};

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

现在考虑这些指针:

Shape *ps; 						//静态类型为Shape*
Shape *pc = new Circle;			//静态类型为Shape*
Shape *pr = new Rectangle;		//静态类型为Shape*

ps,pc,pr,都被声明为pointer-to-Shape类型,所以他们都以它为静态类型,
对象的所谓动态类型,则是指"目前所指对象的类型".也就是说,动态类型可以表现出一个对象将会发生什么行为;pc的动态类型为Circle*,pr的动态类型为Rectangle *,ps没有动态类型

virtual函数是动态绑定,而缺省参数值却是静态绑定,意思是你可能会在"调用一个定义于derived class内的virtual函数的同时,却使用base class为它所制定缺省参数值":

pr->draw(); 	// 调用Rectangle::draw(Shape::Red)

为什么C++以这种方式来运作呢? 答案在于运行效率,如果缺省参数值是动态绑定,编译器就必须有某种办法在运行期为virtual函数决定适当的参数缺省值,这比目前实行的"在编译器决定"的机制更慢而且更加复杂;

但是如果你同时提供缺省参数值给basederived class用户,又会发生什么事情的?

clas 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;
};

上述代码重复又带着相依性;如果Shape内的缺省参数值改变了,derived classes也必须改变;解决办法是令base class内的一个public non-virtual函数调用private virtual函数,后者可被derived classes重新定义

clas Shape {
public:
	enum ShapeColor{ Red, Green, Blue};
	void draw(ShapeColor color = Red) const {
		doDraw(color);
	}
private:
	virtual void doDraw(ShapeColor color) const =0; // 真正的工作在此处完成
};

class Rectangle : public Shape {
public:
	//...
private:	
	virtual void doDraw(ShapeColor color) const; //无需指定缺省参数值
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值