加油鸭
运算符重载
运算符重载可以分为成员函数重载和非成员函数重载,由于成员函数重载存在一定缺陷,可以用友元声明非成员函数重载。
例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40//mytime0.h
class Time
{
private:
int hours;
int minutes;
public:
Time(){hours=minutes=0;}
Time(int h,int m=0){hours=h+m/60;minutes=m%60;}
void show()const{std::cout<<hours<<" hours, "<<minutes<<" minutes\n";}
//operator
Time operator+(const Time &t)const//返回类型不要使用引用
{
Time sum;
sum.minutes=minutes+t.minutes;
sum.hours=hours+t.hours;
sum.hours=sum.hours+sum.minutes/60;
sum.minutes%=60;
return sum;
}
Time operator*(const int &v)const//另一种重载方式,非同类型重载
{
return Time(hours*v,minutes*v);
}
};
//main.cpp
using namespace std;
int main()
{
Time thetime=Time(12,15);
thetime.show();
Time lxttime=Time(11,5);
thetime=thetime+lxttime;
thetime.show();
}重载限制
- 重载后的运算符必须至少一个操作数是用户定义的类型.
- 使用运算符重载不能违反运算符原来的句法规则 : 操作数的个数 和 优先级
- 不能创建新运算符
- 有些运算符不能重载
- 有些运算符只能通过成员函数重载 ,而不能通过非成员函数重载.
在运算符表示法中,运算符左侧的对象是调用对象,运算符右边的对象最作为参数被传递的对象。
友元函数
- 友元函数访问权限和成员函数相同。
- 重载语法问题
1
2thetime=thetime*2;//allowed
thetime=2*thetime;//not allowed
解决办法: 我们只能使用非成员函数解决改问题,但常规非成员函数不能访问私有成员,只有一类特殊的非成员函数可以访问类的私有成员-友元函数。
- 友元函数声明
- 原型放在类中,但不是类成员函数,不用使用::
- 前加friend,定义不用加,可访问类的私有成员。
1
friend Time operator*(double m,const Time &t);
- 前加friend,定义不用加,可访问类的私有成员。
友元函数定义
- 不用加friend
- 不用加 类名::
常见的友元函数
1
2
3
4
5ostream & operator<<(ostream & os,const c_name &obj)
{
os << ...;
return os;
}改进后的Time类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Time
{
private:
int hours;
int minutes;
public:
Time(){hours=minutes=0;}
Time(int h,int m=0){hours=h+m/60;minutes=m%60;}
void show()const{std::cout<<hours<<" hours, "<<minutes<<" minutes\n";}
//operator
Time operator+(const Time &t)const//返回类型不要使用引用
{
Time sum;
sum.minutes=minutes+t.minutes;
sum.hours=hours+t.hours;
sum.hours=sum.hours+sum.minutes/60;
sum.minutes%=60;
return sum;
}
Time operator*(const int &v)const//另一种重载方式,非同类型重载
{
return Time(hours*v,minutes*v);
}
friend Time operator*(int v,const Time &t)
{
return t*v;
}
friend std::ostream &operator<<(std::ostream &os,const Time &t)
{
os<<t.hours<<" hours, "<<t.minutes<<" minutes\n";
return os;
}
};
//main.cpp
using namespace std;
int main()
{
Time thetime=Time(12,15);
thetime=2*thetime;//allowed
cout<<thetime<<endl;
return 0;
}
类的转换
其他类型转换成类
- 只含有一个参数的构造函数可以作为转换函数,进行自动(隐式转换)。
构造时应避免二义性。
1
2
3Time(int h);//构造函数
Time mytime;
mytime=16;explicit关键字: 有时候不需要这种自动特性,声明时使用该关键字即可。
1
2
3
4explicit Time(int h)
Time mytime=16;//not allowed
mytime=Time(16);//allowed
mytime=(Time)16;//allowed
类转换成其他类型
- 应避免二义性。
- 有时候会出现错误,故在声明转换函数时加上explicit,并使用显式转换。
- 或者另外声明一个成员函数来进行类型转换。
声明
1
explicit operator int() const
定义
1
2
3
4Time::explicit operator int()const
{
return hours;
}