先介绍一下重载。
有了C++语言,你就可以重载函数和运算符。重载是一种应用,它在同一范围中为一个给定函数名称提供了多种定义。委托编译器依据调用该函数的参量选择合适的函数或运算符的版本。例如:
double max(double d1,double d2) { return (di>d2)?d1:d2; } int max (int e1,int e2) |
作为一个重载函数,函数max在程序中使用如下:
main() |
在第一个例子中,要求出两个整型变量的最大值,故调用函数(int,int)。然而,在第二种情况下,两个参量是浮点型,因此调用的函数是max(double,double)。
重载函数之间的区别在于带有不同初始值的参量类型。因而对一个给定类型的参量以及对于该类型的引用,在重载的意义上来说是完全相同的。它们被看成是相同的,因为它们采用了相同的初始值。例如:max(double,double)和(double&,double &)是完全相同的,说明两个这样的函数会引起错误。出于相同的原因,用修饰符const和volatile进行修饰的函数参量类型同基本类型,在重载的意义上看没有什么不同。然而重载函数的机制可以区分由const或volatile修饰的引用以及基本类型的引用。指向const和volatile对象的指针和指向其基本类型的指针在重载意义上是不同的。
一组重载函数是否是可接受的如下限制:
·该组重载函数中任何两个都必须有不同的参量表。 ·具有相同类型参量表、仅在返回值类型上不同的重载函数会引起错误。 ·成员函数的重载不能仅基于一个说明为静态的,另一个说明为非静态的。 ·typedef说明并未定义新的类型,它们仅为已存在的类型引入了一个同义词。它们不能影响重载机制。 ·枚举类型是一些可区分的类型,故可以区分重载函数。 ·从区分重载函数的意义上说,类型“数组”和“指针”是相同的。对于一维数组来说是正确的。 |
了解了函数重载,下面将具体的介绍运算符重载
注意,下面的规则约束着重载运算符如何实现,但它们并不适用于new和delete运算符。
·运算符必须要么是成员函数,或者带有某个类的参量,或者是枚举类型的参量、或者带有某个类的引用、或某个枚举的类型的引用。 ·运算符要遵守它们同内部类型一起使用所指定的优先原则、分组及操作数的个数。因此,无法表达把2及3加到一个Point对象中的含义,除了把2加到X坐标中,把3加到Y坐标中。 ·单目运算符说明为成员函数不带参量;如果说明为全局函数,要带一个参量。双目运算符说明为成员函数只带一个参量;如果说明为全局函数,要带两个参量。 ·所有的重载运算符除了赋值(operator=)外均可被派生类继承。 ·重载运算符的成员函数的第一个参量总是激活该运算符的对象的类类型参量(运算符被定义的类,或者定义了运算符的类的派生类)。对于第一个参量也不支持转换。 |
任何运算符的意义都可能被完全地改变了,这包括取地址(&)、赋值(=)、函数调用运算符的含义。同理,内部的类型可由于使用了运算符重载而改变。例如:下面四条语句在完成求值以后完全等同:
s=s+1; |
对于重载了运算符的类类型来说,这种确信是靠不住的,而且,对于在基本类型中使用这些运算符的隐含条件,对于重载的运算符来说是放松了。例如:加法/赋值操纵符,在应用于基本类型时,要求其左操作数是l值的;但此运算符重载以后就没有这种要求了。
下面给出可重载的单目运算符:
clearcase/" target="_blank" >cc>运算符 | 名称 |
! | 逻辑非 |
& | 取地址 |
~ | 求补 |
* | 指针间接引用 |
+ | 单目加 |
++ | 增1 |
- | 单目取反 |
-- | 减1 |
如果说明一个单目运算符为一个非静态成员,必须按如下形式进行说明:
ret-type operator op() |
其中ret-type是返回类型,而op是上表中的某个运算符。
说明一个单目运算符为全局函数,必须按如下形式说明:
ret-type operator op(arg) |
其中ret-type和op的含义同成员运算符函数中的描述,而arg是对其操作的类类型参量。
注意:对于单目运算符的返回值没有限制。例如,对于一个逻辑非运算符,返回一个必要的值是合适的。但这一点不是必须的。
双目运算符
下表给出了可被重载的运算符。
运算符 | 名称 |
, | 逗号 |
!= |
不等 |
% | 取模 |
%= | 取模/赋值 |
& | 按位和 |
&& | 逻辑和 |
&= | 按位和/赋值 |
* | 乘法 |
*= | 乘法/赋值 |
+ | 加法 |
+= | 加法/赋值 |
- | 减法 |
-= | 减法/赋值 |
-> | 成员选择 |
->* | 指向成员的指针选择 |
/ | 除法 |
/= | 除法/赋值 |
< | 小于 |
<< | 左移 |
<<= | 左移/赋值 |
<= | 小于等于 |
= | 赋值 |
== | 等于 |
> | 大于 |
>= | 大于/等于 |
>> | 右移 |
>>= | 右移/赋值 |
^ | 异或 |
| | 按位或 |
|= | 按位或/赋值 |
|| | 逻辑或 |
说明一个双目运算符函数为非静态成员函数,必须按如下形式说明:
ret-type oprator op(arg) |
其中ret-type是返回类型,op是上表中列出的某个运算符,而arg则是一个任意类型的参量。
说明一个双目运算符为全局函数,必须按如下形式说明:
ret-type operator op(arg1, arg2) |
其中ret-type和op同成员函数中的描述是一致的,而arg1和arg2是参量。至少其中之一必须是类类型。
注意:对于双目运算符的返回类型没有限制;然而大多数用户自定义型双目运算符返回类类型或类类型的引用。
这里顺便提一下赋值,赋值运算符严格地说是一个双目运算符。它的说明等同于其它双目运算符的说明,但下列情况除外。 它必须是非静态成员函数。没有operator=可以说明为非成员函数。它不能被派生类继承。 如果不存在缺省的operator=函数,则编译器会为该类生成一个缺省的函数。
关于输入输出流,由于涉及内容磅多,本文只能挑选一部分io流加以介绍,更多内容请参阅相关手册。