运算符重载定义
returnType operator op(argument-list);
这种方式成为成员重载运算符函数
。
头文件
//
// Created by Biter on 2019/10/21.
//
#ifndef NDK_MYTIME_H
#define NDK_MYTIME_H
#include <iostream>
using namespace std;
class Time {
private:
int hours;
int minutes;
public:
Time();
Time(Time &time);
Time(int h, int m = 0);
void addMin(int m);
void addHr(int h);
Time sum(const Time &t) const;
void show() const;
void reset(int h = 0, int m = 0);
Time operator +(const Time& time);//只看这个
~Time();
};
#endif //NDK_MYTIME_H
实现文件
//
// Created by Biter on 2019/10/21.
//
#include "mytime.h"
Time::Time() {
hours = minutes = 0;
std::cout << "默认构造函数" << std::endl;
}
Time::Time(Time &time) {
hours = time.hours;
minutes = time.minutes;
std::cout << "拷贝构造函数" << std::endl;
}
Time::Time(int h, int m) {
hours = h;
minutes = m;
std::cout << "双参构造函数" << std::endl;
}
Time::~Time() {
std::cout << "析构函数" << std::endl;
}
void Time::addHr(int h) {
hours += h;
}
void Time::addMin(int m) {
minutes += m;
}
void Time::reset(int h, int m) {
hours = h;
minutes = m;
}
void Time::show() const {
std::cout << "hours = " << hours << " ;minutes = " << minutes << std::endl;
}
Time Time::sum(const Time &t) const {
Time time;
std::cout << "局部函数对象的地址 = " << &time << std::endl;
time.minutes = minutes + t.minutes;
time.hours = hours + t.hours + time.minutes / 60;
time.minutes %= 60;
return time;
}
Time Time::operator+(const Time &time) {
Time t;
t.minutes = minutes + time.minutes;
t.hours = hours + time.hours + t.minutes / 60;
t.minutes %= 60;
return t;
}
调用重载运算符
//
// Created by Biter on 2019/10/21.
//
#include "mytime.h"
int main() {
Time time;
std::cout << "main 局部函数对象的地址 = " << &time << std::endl;
time.reset(2, 90);
Time time1;
time1.reset(1, 10);
time1 = time1 + time;
time1.show();
std::cout << "main 局部函数对象的地址 = " << &time1 << std::endl;
return 0;
}
time1 = time1 + time;
实则调用time1 = time1.operator+(time);
注意,运算符op
左侧是的对象是调用对象
,右侧的对象是作为参数被传递的对象,即右侧为实参
。
友元函数
大多数运算符都可以通过成员或者非成员函数的方式来重载。
从数学定义上来讲3.25 * time
与time*3.25
是等价的。后者可以通过重载乘法运算符来实现,前者则无法通过成员函数重载运算符的方式来实现,因为3.25
不是类对象,不能调用成员函数。由此产生问题1:重载调用问题。
非成员不是有对象调用的,它所使用的值都是显式的,比如
Time t = 3.25 * time;
该表达式与下面的调用匹配:
Time t = operator*(3.25,time);
该调用与下面的原型匹配:
Time operator*(double m,const Time & t);
对于非成员重载运算符来说,运算符表达式左边的操作数对应运算符函数的第一个参数
,右边的操作数对应着第二个参数
。
非成员函数解决了调用问题,但是这样存在一个新问题,它不能访问对下的私语属性,即产生问题2,访问问题。
然而,有一类特殊的函数可以访问类的私有属性,它们被称为友元函数
。
创建友元函数
前面讲述乘法操作符重过程中遇到的两个问题,一是操作符函数的调用问题,二是私有成员的访问问题,及其解决方案:友元函数。
第一步:声明友元函数。
创建友元函数的第一步就是将其原型放在类的声明中,并在原型前面加上关键字friend
:
friend Time operator*(double m,const & Time);
- 这样声明的函数意味着:
- 虽然函数实在类中声明的,但是他不是成员函数,因此不能使用成员重载的运算符来调用。
- 虽然不是成员函数,但是有着与成员函数的相同的访问权限。
第二步,定义友元函数
因为不是成员函数,所以定义的时候不加类的作用域限定符,也就是函数定义前面不加Time::
限定符,此外不要再定义中使用friend
关键字:
友元运算符重载函数
上面提到过,对于非成员重载运算符来说,运算符表达式左边的操作数对应运算符函数的第一个参数,右边的操作数对应着第二个参数。这里只是深化以下这个应用。
重载 <<
Time trip;
重载输出流操作符,使其可以输出一个对象
cout<<trip;
1、使用成员函数重载
那么操作符左边的值必须是此类的对象,即
trip<<cout;
这种方式与以往的输出流用法有些不一致,显得编程不友好。
2、使用友元函数重载操作符
原型如下:
void operator<<(ostream & os,const Time & time);
实现如下:
void operator<<(ostream & os,const Time & time){
os<<t.hours<<" houes; "<<t.minutes<<" minutes";
}
调用
cout<<trip;
3、高级版本
满足链式调用
ostream & operator<<(ostream & os,const Time & time){
os<<t.hours<<" houes; "<<t.minutes<<" minutes";
return os;
}
成员还是友元
成员函数重载运算符
成员函数重载运算符,其参数比操作数少一个,因为其中一个被隐式地传递的调用对象。在原型中,做操作数被隐式地传递给函数,右操作数对应着参数对应。如:
Time Time::operator+(const Time &time) {
Time t;
t.minutes = minutes + time.minutes;
t.hours = hours + time.hours + t.minutes / 60;
t.minutes %= 60;
return t;
}
友元函数重载运算符
友元函数重载运算符,其参数有操作数的木梳一样,两个操作数都作为参数传递。在原型中,左操作数对应第一个参数,右操作数对应第二个参数。如
cout<<trip;
ostream & operator<<(ostream & os,const Time & time){
os<<t.hours<<" houes; "<<t.minutes<<" minutes";
return os;
}
网友评论