一、运算符重载
①含义
函数重载或函数多态:同名函数完成相同的基本操作
C++将重载的概念扩展到运算符上,于是出现了运算符重载
C++中有很多运算符已经被重载
*
运算符,运用于地址,可以得到存储在这个地址的值;运用于两个数字,得到是两个数字的乘积
C++会根据操作数的数目和类型来决定采用哪种操作
C++允许将运算符重载扩展到用户定义的类型中,例如类,允许使用+
将两个对象相加
②格式
operatorop(argument-list)
例如:operator+()
、operator*()
等
其中op
必须是一个有效的C++运算符,不能虚构,例如:operator@()
,C++中没有@运算符
假设有一个Animal类有两个对象,dog和cat,并定义了operator+()
成员函数重载+
运算符,当两个对象相加时,编译器发现操作数都是Animal对象,则会使用相应的运算符函数来进行替换
animal = dog + cat;
animal = dog.operator+(cat);
二、实操举例
小明早上上班通勤花费2h35min,晚上下班通勤花费2h40min,则一天上下班共花费多少时间在通勤上?
Ⅰ重载常规做法
①time.h
定义一个Time类,当分钟超过59时,函数AddMinutes()和Sum()方法会使用整数除法和求模运算符进行调整
#pragma once
#ifndef TIME_H_
#define TIME_H_class Time
{
private:int hour_;int minute_;public:Time();Time(int hours, int minutes);void AddMinutes(int minutes);void AddHours(int hours);void Reset(int hours = 0, int minutes = 0);Time Sum(const Time& time) const;void PrintTime() const;
};#endif // !TIME_H_
②time.cpp
不要返回执行局部变量或临时对象的引用,函数执行完毕后,局部变量和临时对象都会消失,引用将指向不存在的数据
这里的Sum函数返回类型是Time,而非引用
#include <iostream>
#include "time.h"Time::Time()
{hour_ = 0;minute_ = 0;
}Time::Time(int hour, int minute)
{hour_ = hour;minute_ = minute;
}void Time::AddMinutes(int minutes)
{minute_ += minutes;hour_ += minute_ / 60;minute_ %= 60;
}void Time::AddHours(int hours)
{hour_ += hours;
}void Time::Reset(int hour, int minute)
{hour_ = hour;minute_ = minute;
}//Time,返回类型是Time,而不是引用;返回类型不能是引用,需要创建对象的副本;若为返回类型为引用时,sum对象是局部变量,函数结束会被删除
//const Time& t,参数是引用
Time Time::Sum(const Time& t) const
{Time sum;sum.minute_ = minute_ + t.minute_;sum.hour_ = hour_ + t.hour_ + sum.minute_ / 60;sum.minute_ %= 60;return sum;
}void Time::PrintTime() const
{std::cout << hour_ << ":" << minute_ << std::endl;
}
③main.cpp
#include <iostream>
#include "time.h"int main()
{Time go_to_work(2, 45);Time work_time(6, 30);Time go_home(3, 15);Time total_time;std::cout << "go_to_work time is: ";go_to_work.PrintTime();std::cout << std::endl;std::cout << "work_time time is: ";work_time.PrintTime();std::cout << std::endl;std::cout << "go_home time is: ";go_home.PrintTime();std::cout << std::endl;total_time = go_to_work.Sum(work_time.Sum(go_home));std::cout << "total_time is: ";total_time.PrintTime();std::cout << std::endl;return 0;
}
运行结果:
可以看到,上班通勤2h45min,工作6h30min,下班通勤3h15min,一天总用12h30min
Ⅱ重载加法运算符
常规做法看起来很麻烦
total_time = go_to_work.Sum(work_time.Sum(go_home));
不如直接使用重载加法运算符操作便捷
total_time = go_to_work + work_time + go_home;
重载加法运算符很简单,只需要将Sum()
改成operator+()
即可
①time.h
原先:Time Sum(const Time& time) const;
现在:Time operator+(const Time& time) const;
#pragma once
#ifndef TIME_H_
#define TIME_H_class Time
{
private:int hour_;int minute_;public:Time();Time(int hours, int minutes);void AddMinutes(int minutes);void AddHours(int hours);void Reset(int hours = 0, int minutes = 0);//Time Sum(const Time& time) const;Time operator+(const Time& time) const;void PrintTime() const;
};#endif // !TIME_H_
②time.cpp
原先:Time Time::Sum(const Time& t) const
现在:Time Time::operator+(const Time& t) const
#include <iostream>
#include "time.h"Time::Time()
{hour_ = 0;minute_ = 0;
}Time::Time(int hour, int minute)
{hour_ = hour;minute_ = minute;
}void Time::AddMinutes(int minutes)
{minute_ += minutes;hour_ += minute_ / 60;minute_ %= 60;
}void Time::AddHours(int hours)
{hour_ += hours;
}void Time::Reset(int hour, int minute)
{hour_ = hour;minute_ = minute;
}/*
//Time,返回类型是Time,而不是引用;返回类型不能是引用,需要创建对象的副本;若为返回类型为引用时,sum对象是局部变量,函数结束会被删除
//const Time& t,参数是引用
Time Time::Sum(const Time& t) const
{Time sum;sum.minute_ = minute_ + t.minute_;sum.hour_ = hour_ + t.hour_ + sum.minute_ / 60;sum.minute_ %= 60;return sum;
}
*/
Time Time::operator+(const Time& t) const
{Time sum;sum.minute_ = minute_ + t.minute_;sum.hour_ = hour_ + t.hour_ + sum.minute_ / 60;sum.minute_ %= 60;return sum;
}void Time::PrintTime() const
{std::cout << hour_ << ":" << minute_ << std::endl;
}
③main.cpp
原先:total_time = go_to_work.Sum(work_time.Sum(go_home));
现在:total_time = go_to_work.operator+(work_time.operator+(go_home));
等价于:total_time1 = go_to_work + work_time + go_home;
在运算符表示法中,运算符左侧的对象(go_to_work )是调用对象,运算符右边的对象(work_time + go_home)是作为参数被传递的对象
+
运算符是从左向右结合的运算符
首先work_time.operator+(go_home)
返回一个Time对象,work_time
和go_home
的和,然后这个和作为go_to_work.operator+()
的参数,得到go_to_work
和work_time
、go_home
之和
#include <iostream>
#include "time.h"int main()
{Time go_to_work(2, 45);Time work_time(6, 30);Time go_home(3, 15);Time total_time, total_time1;std::cout << "go_to_work time is: ";go_to_work.PrintTime();std::cout << std::endl;std::cout << "work_time time is: ";work_time.PrintTime();std::cout << std::endl;std::cout << "go_home time is: ";go_home.PrintTime();std::cout << std::endl;//total_time = go_to_work.Sum(work_time.Sum(go_home));total_time = go_to_work.operator+(work_time.operator+(go_home));total_time1 = go_to_work + work_time + go_home;std::cout << "total_time is: ";total_time.PrintTime();std::cout << std::endl;std::cout << "total_time1 is: ";total_time1.PrintTime();std::cout << std::endl;return 0;
}
运行结果:
三、限制
看到这里,我想家人们应该会理解了,运算符重载其实就是这么一回事,没那么难
说白了就是operatorop
去替代函数名称
而已,例如operator+()
替代Sum()
运算符重载理解了,家人们可以随意去发挥去秀操作,但运算符重载是有限制的
重载的运算符不必是成员函数,但必须至少有一个操作数是用户定义的类型!
使用运算符时不能反运算符原来的句法规则,例如不能将求模运算符(%)重载成使用一个操作数,例如int x; Time t; % x; % t;
同样不能修改运算符的优先级,若将+
运算符重载为两个类相加,则新的运算符与原来的+
具有相同的优先级
还有一些运算符不可以重载,家人们可以去网上搜索一下对应的表格
以下是不可重载的运算符和可重载的运算符
1,不可重载的运算符:
2,可重载的运算符
本篇博文参考《C++ Primer Plus(第6版)》若有侵权,联系立删