第11章 使用类
- 运算符重载
运算符重载是一种形式的c++多态(还有函数重载)。可以让同名符号或函数 用于不同数据类型或根据传入参数不同执行不同操作。
C++允许运算符重载扩展到用户定义的类型,比如允许+将两个对象相加,运算符函数形式如下:operator+()重载+号。但注意不能重载C++中没有的运算符如@。
Eg:重载+号使Time类的对象可加
Class time
{
private:
int hour;
int min;
public:
time();
timeoperator+( const time & t) const;
}
timeoperator+( const time & t) const
{
time Sum;
Sum.min = min + t.min;
Sum.hour = hour + t.hour+ t.min/60;
Sum.min %=60;
return Sum
}
由于+为从左到右结合的运算符,当出现t4=t1+t2+t3;函数会被转为:t4=t1. operator+( t2. operator+(t3));由于重载符号返回值为Time类型,因此可以实现连加。
- 重载限制
(1) 重载后的运算符至少有一个操作符是用户定义的类型,如不能将-重载为两double类型的和。
(2) 使用运算符时不能违反运算符原来的句法规则,不能修改运算符优先级。
(3) 不能创建新运算符
(4) 不能重载以下运算符:sizeof, 成员运算符. ,成员指针运算符*,作用域解析运算符::,条件运算符?:,RTTI运算符typeid,强制类型转换运符const_cast, 、dynamic_cast、reinterpret_cast、stastic_cast。
(5) 大多数运算符可通过成员或非成员函数重载,这几个只能通过成员函数重载:赋值运算符=,函数调用(),下标运算符[ ],指针访问类成员运算符->。 - 友元函数
C++中提供除访问私有成员的方法—友元,包括:友元函数,友元类,友元成员函数。创建方式eg:在前面示例中,出现A=5.2B;则不能相乘,因为5.2不是成员函数,需要加入非成员函数Time operator( double m ,const time & t);但非成员函数不能访问类成员,只能通过友元函数实现。
(1) 将函数原型声明friend Time operator*( double m ,const time & t);加入类声明中,该函数不是成员函数,但与成员函数访问权限相同.
(2) 编写函数定义,注意不要在前面加Time::限定符。
Time operator*( double m ,const time & t)
{
…
}
运算符重载时非成员函数应该是友元函数,这样才能直接访问成员函数。 - 类的自动转换和强制类型转换
本节讨论如何处理用户定义类型的转换。可以将类定义成与基本类型或另一个类相关,使得从一种类型转换带另一种类型是有意义的。
(1) 将数字转换为对象
通过接受一个参数的构造函数为将类型与该参数相同的值转换为类提供了蓝图。
Eg:
class Stonewt{
private:
int stone;
double pds_left;
double pounds;
public:
Stonewt(double lbs) ;
Stonewt(double lbs,int stn);
};
Stonewt(double lbs);
Stonewt mycat;
mycat = 19.6;// 通过构造函数Stonewt(double lbs)将19.6转换为Stonewt类型
程序使用构造函数Stonewt(double lbs)创建一个临时对象,并将19.6作为初始化值,该过程为隐式转换。隐式转换的情况有:
a.将Stonewt对象初始化为double值时
b.将double值赋给Stonewt对象时
c.将double值传递给接收Stonewt参数的函数时
d.返回值被声明为Stonewt的函数试图返回double值时
e.上述情况下,使用可转为double类型的内置类型时。如Stonewt mycat(50),先将50转为int,再转为double3002
如果构造函数有两个参数,必须将第二个参数提供默认值才能作为转换函数。Stonewt(double lbs,int stn=0);
自动转换可能会导致意外类型转换,在声明构造函数前加关键字explicit后,只能显示转换。
Eg: explicit Stonewt(double lbs);
Stonewt mycat;
Mycat=19.6;//非法操作,隐式转换不被允许
Mycat= Stonewt (19.6);//显式转换1
Mycat=( Stonewt)19.6; //显式转换2
(2) 将对象转换为数字
将对象转换为数字需要构造转换函数,转换函数格式如:在类中添加声明operator int ()
Eg:
Stonewt mycat(19.6);
double catvalue= mycat;// 隐式转换
catvalue = int (19.6);// 显式转换1
catvalue =( int)19.6; //显式转换2
同样地,隐式转换可能会导致意外类型转换,此时有两种方法:
(1) 在声明前加入explicit关键字explicit operator double();
(2) 用一个功能相同的非转换函数代替转换函数
double Stonewt_to_int ()
{
return int (pounds+0.5);
}