第11章、使用类

11.1 运算符重载

假如在某个类(sell 类)中使用了operator+()重载运算符。在实际代码如果有以下:

dist=sid+sara;//两个sell类的对象相加

编译器发现,操作数是sell类对象,因此使用相应的运算符函数替换上述运算符

dist=sid.operator+(sara);//两个sell类的对象相加

该函数隐式地使用sid对象(因为它调用了方法),显式地使用了sara 对象(因为它作为参数传递)。

11.2.1 添加加法运算符

将Time类转换为重载的加法运算符,定义一个operator+()成员函数即可
time.h

#ifndef TIME_H
#define TIME_H
class Time{
private:
	int hours;
	int minutes;
public:
	Time();
	Time(int h,int m=0);	
	Time operator+(const Time & t) const;//const函数,没有修改对象本身
}
#endif// TIME_H

time.cpp


#include"time.h"
Time::Time(){
	hours=minutes=0;
}
Time::Time(int h,int m){
	hours=h;
	minutes=m;
}
Time Time::operator+(const Time & t) const{
	Time sum;
	sum.minutes=minutes+t.minutes;
	sum.hours=hours+t.hours+sum.minutes/60;
	sum.minutes %=60;
	return sum; 
}


两种调用方法:
1.

total=code.operator+(fix);//函数调用表示法

2、

total=code+fix;//运算符表示法

两种方法都可行,运算符表示法,运算符左侧对象(code)是调用对象,运算符右边是作为参数被传递的对象。

假如Time类的使用有如下:

t4=t1+t2+t3;

这种是可以通过编译,并且顺利执行的

首先被转换成

t4=t1.operator+(t2+t3);

然后被转换成

t4=t1.operator+(t2.operator+(t3));

函数调用t2.operator+(t3)返回一个Time类对象,后者是t2和t3的和。然后,该对象成为t1.operator+()的参数,该调用返回t1与表示t2和t3之和的Time对象的和。

11.2.2 重载限制

重载的运算符(有些例外情况)不必是成员函数,但必须至少有一个操作数是用户定义的类型。运算符重载有以下限制:

1、重载后的运算符必须至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载运算符。

2、使用运算符时不能违反运算符原来的语法规则,不能修改运算符的优先级

3、不能创新运算符。

4、不能重载以下运算符。

sizeof : sizeof运算符
. :成员运算符
.* :成员指针运算符
::  :作用域解析运算符
?:   :条件运算符
typeid :一个RTTI运算符
const_cast :强制类型转换运算符
dynamic_cast:强制类型转换运算符
reinterpret_cast :强制类型转换运算符
static_cast :强制类型转换运算符


5、表11.1 的大多数运算符都可以通过成员或非成员函数进行重载,但是下面的运算符只能通过成员函数进行重载。

= :赋值运算符
() :函数调用运算符
[] :下标运算符
->  :通过指针访问类成员的运算符

在这里插入图片描述
除了这些正式限制之外,还有其他的一些明智限制。例如:不要将*运算符重载成交换两个Time对象的数据成员。

11.3 友元

友元有三种:
1、友元函数
2、友元类
3、友元成员函数

11.3.1 创建友元

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

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

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

第二步:编写函数定义
因为不是成员函数,因此不要使用Time:: 限定符。另外,不要在定义中使用关键字,定义如下:

Time  operator *(double m,const Time & t){
	Time res;
	res.hour= t.hour* m;
	return res;
}

11.3.2 常用的友元:重载<<运算符

1、<<的第一种重载版本

void operator <<(ostream &os; const Time &t){
os<<t.hour<<" hour ,"<<t.minutes <<" minutes";
}

这样可以使用如下语句:

cout<<trip;

2、<<的第二种重载版本

ostream & operator <<(ostream &os; const Time &t){
	os<<t.hour<<" hour ,"<<t.minutes <<" minutes";
	return os;
}

这样可以使用如下语句:

cout<< " time "<<trip <<"tuesday ";

禁止 隐式类型转换

explicit 禁止隐式类型转换,只允许显式类型转换

11.6.1 转换函数

转换函数是用户定义的,可以像使用强制类型转换那样使用它们。

要转换为typeName类型,需要使用这种形式的转换函数

operator typeName();

注意以下几点:
1、转换函数必须是类方法
2、转换函数不能指定返回类型
3、转换函数不能有参数

例如,转换为double类型的函数原型如下:

operator double();

typeName指出了要转换成的类型,因此不需要指定返回类型。转换函数是类方法意味着;它需要通过对象来调用,从而告知函数要转换的值。因此,函数不需要参数。

class Stone{
private:
	double pounds;
public:
	operator int ()const;
}
Stone::operator int() const{
	return int (pounds+0.5):
}

11.6.2 转换函数和友元函数

Stone 重载加法运算符。

Stone Stone::operator+(const Stone& st )const{
	double pds=pounds+st.pounds;
	Stone sum(pds);
	return sum;
}

将加法作为友元函数实现:

Stone operator+(const Stone& st1,const Stone& st2  )const{
	double pds=st1.pounds+st2.pounds;
	Stone sum(pds);
	return sum;
}

可以提供方法定义或者友元函数定义,但不能都提供。上面任何一种格式都允许这样做:

Stone jenSt(9,12);
Stone benSt(89,12);
Stone total;
total=jenSt+benSt;

另外,如果提供了Stone (double)构造函数,则也可以这样做:

Stone jenSt(9,12);
//Stone benSt(89,12);
double kenD=17.6;
Stone total;
total=jenSt+kenD;

但只有友元函数才允许这样做:

Stone jenSt(9,12);
//Stone benSt(89,12);
double penD=17.6;
Stone total;
total=penD+jenSt;

为了了解其中的原因,将每一种加法都转换为相应的函数调用。首先:
第一个

total=jenSt+benSt;

被转换为:

total=jenSt.operator+(benSt);//成员函数

或者是

total=operator+(jenSt,benSt);//友元函数

第二个

total=jenSt+kenD;

被转换为:

total=jenSt.operator+(kenD);//成员函数

或者是

total=operator+(jenSt,kenD);//友元函数

第三个

total=penD+jenSt;

被转换为:

total=operator+(penD,jenSt);//友元函数

然而不能调用成员函数。将加法语法转换为函数调用将类似于下面这样:

total=penD.operator+(jenSt);// 没有意义的

将加法定义为友元可以让程序更容易适用自动类型转换。原因在于,两个操作数都成为函数参数,因此与函数原型匹配。

仅供学习:来源《C++ primer plus》
侵删

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值