1、运算符重载
1.1、运算符重载的使用
C++允许将运算符重载扩展到用户自定义的类型,例如对象的相加、比较等等。这种运算符重载隐藏了内部机制,但强调了实质。
运算符重载语法:
operator symbol(argument-list)
class Time
{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m);
Time operator+(const Time &t)const;
void show()const;
};
Time::Time()
{
hours = minutes = 0;
}
Time::Time(int h, int m)
{
minutes = m;
hours = h;
}
Time Time::operator+(const Time &t)const
{
Time time;
time.minutes = minutes + t.minutes;
time.hours = hours + t.hours + time.minutes / 60;
time.minutes = time.minutes % 60;
return time;
}
void Time::show()const
{
cout << hours << " hours, " << minutes << " minutes" << endl;
}
int main()
{
Time time1(2,40); 普通构造函数的隐式调用
Time time2(1,50); 普通构造函数的隐式调用
Time t_time1,t_time2; 默认构造函数的隐式调用
t_time1 = time1 + time2; 运算符重载调用方法一
t_time2 = t_time1 + time2; 运算符重载调用方法二
return 0;
}
1、上述代码中Time Time::operator+(const Time &t)const,显示访问对象为const,隐式访问对象也是const,但是返回的为什么不是const类型?
因为const类型可以赋给非const类型,但是反过来就不行。
2、参数类型为引用,但是返回值不是引用?
参数类型和返回值类型其实没有关联性,主要看你怎么使用,引用做参数比值传递更快,返回非引用是因为我们返回的是局部对象,由前面可知函数执行完毕之后,局部对象会消失,因此引用将指向不存在的数据,存在危险性。
1.2、运算符重载的限制
参考P316
1、 运算符重载不必是成员函数,可以作为友元函数,但是有些运算符必须作为成员函数重载。
2、 至少一个操作数为用户自定义的类型,避免对标准类型运算符重载;
3、 运算符优先级不可修改
4、 不能创建新的运算符
5、 有些运算符不可重载
2、友元函数
2.1、友元函数存在的意义
使用友元函数将使该函数与类的成员函数对于类的数据成员有着相同的访问权限。
1、 友元函数的创建:声明原型放在类中,但是声明前需要加上friend
class Time
{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m);
void show()const;
friend operator+(const Time &t, const Time &s);
};
在类中声明,但不是类的成员函数,不能使用成员运算符调用,但两者访问权限相同。
2、 友元函数的定义:无须使用作用域解析运算法::
friend operator+(const Time &t, const Time &s)
{
Time time;
time.minutes = t.minutes + s.minutes;
time.hours = t.hours + s.hours + time.minutes / 60;
time.minutes = time.minutes % 60;
return time;
}
3、 友元函数的调用
int main()
{
Time time1(1, 40);
Time time2(2, 50);
Time t_time1;
t_time1 = operator+(time1, time2); 方式一
t_time1 = time1 + time2; 方式二
t_time1.show();
return 0;
}
2.2、使用友元函数重载<<
友元函数的使用场景:
参数的顺序问题,友元函数可以反转操作数的顺序
因为成员函数必须通过对象来调用,而友元函数不需要,当非类的项作为第一个操作数时,使用友元函数更加简便
例如:<<,因为成员函数必须为第一操作数,使用如下: time << cout;这样子使用让人迷惑。
第一种版本:
class Time
{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m);
friend void operator<<(std::ostream &os, const Time &t);
};
Time::Time()
{
hours = minutes = 0;
}
Time::Time(int h, int m)
{
minutes = m;
hours = h;
}
void operator<<(std::ostream &os, const Time &t)
{
os << t.hours << " hours, " << t.minutes << " minutes" << endl;
}
int main()
{
Time time(1, 40);
cout << time;
return 0;
}
第二种版本:
class Time
{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m);
friend std::ostream & operator<<(std::ostream &os, const Time &t);
};
Time::Time()
{
hours = minutes = 0;
}
Time::Time(int h, int m)
{
minutes = m;
hours = h;
}
返回的是std::ostream &对象,可以多次输出
std::ostream & operator<<(std::ostream &os, const Time &t)
{
os << t.hours << " hours, " << t.minutes << " minutes" << endl;
return os;
}
int main()
{
Time time1(1, 40);
Time time2(2, 50);
cout << time1 << time2; 多次输出
return 0;
}
|