Chapter11 使用类

Chapter11 使用类

11.1 运算符重载

C++根据操作数的数目和类型决定采取哪种操作。要重载运算符,需使用被称为运算符函数的特殊函数形式,运算符函数的格式如下:

1
operator(argument-list)

不要返回指向局部变量或临时变量的引用。函数执行完毕后,局部变量和临时对象将消失,引用将指向不存在的数据

在运算符表示法中,运算符左侧的对象是调用对象,运算符右边的对象是作为参数被传递的对象。如total=coding+fixingtotal=coding.operator+(fixing)等价。

  • 重载的限制

    (1)重载后的运算符必须至少有一个操作数是用户定义的类型

    (2)使用运算符时不能违反运算符原来的句法规则。

    (3)不能创建新运算符。

    (4)赋值运算符(=)、函数调用运算符(())、下标运算符([])、通过指针访问类成员的运算符(->)都只能通过成员函数进行重载。

11.2 友元

通过让函数称为类的友元,可以赋予该函数与类的成员函数相同的访问权限。

创建友元函数的第一步是将其原型放在类声明中,并在原型声明前加上关键字friend,如:

1
friend Time operator*(double m, const Time & t);

该原型意味着如下两点:
(1) 虽然operator*()函数实在类声明中声明的,但它不是成员函数,因此不能使用成员运算符来调用。
(2) 虽然operator*()函数不是成员函数,但它与成员函数的访问权限相同。

第二步是编写函数定义,因为他不是成员函数,所以不需要使用Time::限定符,另外定义中不需要使用关键字friend,其定义如下:

1
2
3
4
5
6
Time operator*(double m, const Time & t)
{
Time result;
...
return result;
}

一般来说,要冲在<<运算符来显示c_name的对象,可使用一个友元函数,其定义如下:

1
2
3
4
5
ostream & operator<<(ostream & os, const c_name & obj)
{
os << ...;
return os;
}

非成员版本的重载运算符函数所需的形参数目与运算符使用的操作数目相同;而成员版本所需的参数数目少了一个,因为其中一个操作数是被隐式地传递的调用对象。

1
2
Time operator+(const Time & t) const;//member version
friend Time operator+(const Time & t1, const Time & t2); // nonmember version

因为运算符重载是通过函数来实现的,所以只要运算符函数的特征标不同,使用的运算符数量与相应的内置C++运算符相同,就可以多次重载同一个运算符。

只有一个参数的构造函数可以用于将某种类型转换为类类型(explicit可以防止隐式转换)。如果要进行相反的转换,需要使用转换函数,转换函数是用户定义的强制类型转换,可以像使用强制类型转换那样使用它们。

将类类型转换为typeName类型的转换函数为:operator typeName().(转换函数必须是类方法,转换函数不能指定返回类型但必须返回转换后的值,转换函数不能有参数)。