C++高级编程之——函数重载、内联、缺省参数、隐式转换( 三 )

8.2.3 摆脱隐藏
隐藏规则引起了不少麻烦 。示例 8-2-3 程序中 , 语句 pd->f(10)的本意是想调用函
数 Base::f(int) , 但是 Base::f(int)不幸被 Derived::f(char *)隐藏了 。由于数字 10
不能被隐式地转化为字符串 , 所以在编译时出错 。
class Base{public:void f(int x);};class Derived : public Base{public:void f(char *str);};void Test(void){Derived *pd = new Derived;pd->f(10); // error}示例 8-2-3 由于隐藏而导致错误 从示例 8-2-3 看来 , 隐藏规则似乎很愚蠢 。但是隐藏规则至少有两个存在的理由:
? 写语句 pd->f(10)的人可能真的想调用 Derived::f(char *)函数 , 只是他误将参数
写错了 。有了隐藏规则 , 编译器就可以明确指出错误 , 这未必不是好事 。否则 , 编
译器会静悄悄地将错就错 , 程序员将很难发现这个错误 , 流下祸根 。
? 假如类 Derived 有多个基类(多重继承) , 有时搞不清楚哪些基类定义了函数 f 。如
果没有隐藏规则 , 那么 pd->f(10)可能会调用一个出乎意料的基类函数 f 。尽管隐
藏规则看起来不怎么有道理 , 但它的确能消灭这些意外 。
示例 8-2-3 中 , 如果语句 pd->f(10)一定要调用函数 Base::f(int) , 那么将类
Derived 修改为如下即可 。
class Derived : public Base
{
public:
void f(char *str);
void f(int x) { Base::f(x); }
};
8.3 参数的缺省值
有一些参数的值在每次函数调用时都相同 , 书写这样的语句会使人厌烦 。C++语言
采用参数的缺省值使书写变得简洁(在编译时 , 缺省值由编译器自动插入) 。
参数缺省值的使用规则:
z 【规则 8-3-1】参数缺省值只能出现在函数的声明中 , 而不能出现在定义体中 。
例如:
void Foo(int x=0, int y=0); // 正确 , 缺省值出现在函数的声明中
void Foo(int x=0, int y=0) // 错误 , 缺省值出现在函数的定义体中
{

}
为什么会这样?我想是有两个原因:一是函数的实现(定义)本来就与参数是否有缺省值无关 , 所以没有必要让缺省值出现在函数的定义体中 。二是参数的缺省值可能会改动 , 显然修改函数的声明比修改函数的定义要方便 。
z 【规则 8-3-2】如果函数有多个参数 , 参数只能从后向前挨个儿缺省 , 否则将导致函数调用语句怪模怪样 。
正确的示例如下:
void Foo(int x, int y=0, int z=0);
错误的示例如下:
void Foo(int x=0, int y, int z=0);
要注意 , 使用参数的缺省值并没有赋予函数新的功能 , 仅仅是使书写变得简洁一些 。
它可能会提高函数的易用性 , 但是也可能会降低函数的可理解性 。所以我们只能适当地使用参数的缺省值 , 要防止使用不当产生负面效果 。示例 8-3-2 中 , 不合理地使用参数的缺省值将导致重载函数 output 产生二义性 。
#include <iostream.h>void output( int x);void output( int x, float y=0.0);void output( int x){ cout << " output int " << x << endl ;}void output( int x, float y){ cout << " output int " << x << " and float " << y << endl ;}void main(void){ int x=1; float y=0.5;// output(x); // error! ambiguous call output(x,y); // output int 1 and float 0.5}示例 8-3-2 参数的缺省值将导致重载函数产生二义性8.4 运算符重载
8.4.1 概念
在 C++语言中 , 可以用关键字 operator 加上运算符来表示函数 , 叫做运算符重载 。
例如两个复数相加函数:
Complex Add(const Complex &a, const Complex &b);
可以用运算符重载来表示:
Complex operator +(const Complex &a, const Complex &b);
运算符与普通函数在调用时的不同之处是:对于普通函数 , 参数出现在圆括号内;
而对于运算符 , 参数出现在其左、右侧 。例如
Complex a, b, c;

c = Add(a, b); // 用普通函数
c = a + b; // 用运算符 +
如果运算符被重载为全局函数 , 那么只有一个参数的运算符叫做一元运算符 , 有两
个参数的运算符叫做二元运算符 。
如果运算符被重载为类的成员函数 , 那么一元运算符没有参数 , 二元运算符只有一


推荐阅读