C++学习笔记之运算符重载
2014-08-14 10:57
507 查看
一、运算符重载基本知识
在前面的一篇博文
C++学习笔记之模板(1)——从函数重载到函数模板
中,介绍了函数重载的概念,定义及用法,函数重载(也被称之为函数多态)就是使用户能够定义多个名称相同但特征标(参数列表)不同的函数,目的是在对不同类型的参数执行相同的操作时只用一个同名的函数。
运算符重载,就是使同一个运算符在面临不同类型的数据时作出不同的操作(函数重载是操作相同),就是让同一个运算符有多重功能。实际上我们经常用的许多运算符已被重载,例如,将*用于地址,将得到存储在这个地址中的值;但将它用于两个数字时,得到的将是它们的乘积。
C++允许将运算符重载扩展到用户定义的类型,如允许使用+将两个对象相加,编译器根据操作的数目和类型决定使用哪种加法的定义。
运算符重载格式如下:
operator运算符();
例如,operator+()重载+运算符,operator-()重载-运算符等。但是被重载的运算符必须是有效的C++运算符,不能自创一个新的符号。
二、运算符重载示例
假设写一篇博客,上午花了1小时42分钟编码,下午又花了2小时33分钟修改,要计算总共花的时间,很显然与加法概念很吻合,但是要相加的单位是小时与分钟的混合,与内置的加法类型不匹配。采用一个使用方法来处理加法的Time类。作为对比,首先使用常规方法,建立一个名为sum()的函数,然后介绍使用重载运算符。
函数的方法:
运行结果:
运算符重载的方法:
这里所举例子比较简答,我们只需要将sum()名称改为operator+()即可。程序清单如下:
总之,operator+()函数名使得可以使用函数表示法或运算符表示法来调用它。
如果t1,t2,t3,t4都是Time对象,可以这样操作吗:
t4 = t1 + t2 +t3;
我们来仔细分析下,+是从左向右结合的运算符,根据上述代码中的函数,上述语句首先被转换为:
接着继续转换为:
上述语句合法吗?当然合法,因为 t2.operator+(t3)返回一个Time对象,是t2和t3的和,该对象又成为函数调用t1.operator+()的参数,该调用返回t1与表示t2和t3之和的Time对象的和。最后返回值为t1,t2,t3之和,正是我们想要的结果。可以看出,运算符重载实现运算功能要比函数看起来更加自然一些。
三、重载的限制
多数C++运算符都可以用这样的方式重载。但是没有绝对的自由。主要限制有如下几条:
重载后的运算符至少有一个操作数是用户定义的类型。这将防止用户为标准类型重载运算符。假如没有这个限制,我们可以将-重载为两个double相加,而不是它们的差,就乱套了。
使用运算符不能违反运算符原来的句法规则。例如。不能将求模运算符(%)重载成使用一个操作数:% x.同时不能修改运算符的优先级。
不能创建新的运算符。例如,不能定义operator**()函数来表示求幂。
不能重载如下运算符:
sizeof sizeof运算符
. 成员运算符
.* 成员指针运算符
:: 作用域解析运算符
?: 条件运算符
typeid 一个RTTI运算符
const_cast
dynamic_cast
reinterpret_cast
static_cast
5. 大多数运算符都可以通过成员或者非成员函数重载,但是下面的运算符只能通过成员函数重载
= 赋值运算符
() 函数调用运算符
[] 下表运算符
-> 通过指针访问类成员的运算符。
在前面的一篇博文
C++学习笔记之模板(1)——从函数重载到函数模板
中,介绍了函数重载的概念,定义及用法,函数重载(也被称之为函数多态)就是使用户能够定义多个名称相同但特征标(参数列表)不同的函数,目的是在对不同类型的参数执行相同的操作时只用一个同名的函数。
运算符重载,就是使同一个运算符在面临不同类型的数据时作出不同的操作(函数重载是操作相同),就是让同一个运算符有多重功能。实际上我们经常用的许多运算符已被重载,例如,将*用于地址,将得到存储在这个地址中的值;但将它用于两个数字时,得到的将是它们的乘积。
C++允许将运算符重载扩展到用户定义的类型,如允许使用+将两个对象相加,编译器根据操作的数目和类型决定使用哪种加法的定义。
运算符重载格式如下:
operator运算符();
例如,operator+()重载+运算符,operator-()重载-运算符等。但是被重载的运算符必须是有效的C++运算符,不能自创一个新的符号。
二、运算符重载示例
假设写一篇博客,上午花了1小时42分钟编码,下午又花了2小时33分钟修改,要计算总共花的时间,很显然与加法概念很吻合,但是要相加的单位是小时与分钟的混合,与内置的加法类型不匹配。采用一个使用方法来处理加法的Time类。作为对比,首先使用常规方法,建立一个名为sum()的函数,然后介绍使用重载运算符。
函数的方法:
//mytime0,未使用运算符重载 #ifndef MYTIME0_H #define MYTIME0_H class Time { private: int hours; int minutes; public: Time(); Time(int h, int m = 0); void addMin(int m); void addHr(int h); void reset(int h = 0, int m = 0); Time sum(const Time & t ) const; void show() const; }; #endif
#include <iostream> #include "mytime0.h" Time::Time() { hours = minutes = 0; } Time::Time(int h, int m) { hours = h; minutes = m; } void Time::addMin(int m) { minutes += m; hours += minutes / 60; minutes %= 60; } void Time::addHr(int h) { hours += h; } void Time::reset(int h, int m) { hours = h; minutes = m; } Time Time::sum(const Time & t) const { Time result; result.minutes = minutes + t.minutes; result.hours = hours + t.hours +result.minutes / 60; result.minutes %= 60; return result; } void Time::show() const { std::cout << hours << " hours, " << minutes << " minutes"; }
/*usetime0*/ #include <iostream> #include "mytime0.h" int main() { using std::cout; using std::endl; Time planning; Time coding(1, 42); Time fixing(2, 33); Time total; cout << "planning time = "; planning.show(); cout << endl; cout << "coding time = "; coding.show(); cout << endl; cout << "fixing time = "; fixing.show(); cout << endl; total = coding.sum(fixing); cout << "coding.sum(fixing) = "; total.show(); cout << endl; return 0; }
运行结果:
运算符重载的方法:
这里所举例子比较简答,我们只需要将sum()名称改为operator+()即可。程序清单如下:
//mytime0,未使用运算符重载 #ifndef MYTIME0_H #define MYTIME0_H class Time { private: int hours; int minutes; public: Time(); Time(int h, int m = 0); void addMin(int m); void addHr(int h); void reset(int h = 0, int m = 0); Time operator+(const Time & t ) const; void show() const; }; #endif
#include <iostream> #include "mytime0.h" Time::Time() { hours = minutes = 0; } Time::Time(int h, int m) { hours = h; minutes = m; } void Time::addMin(int m) { minutes += m; hours += minutes / 60; minutes %= 60; } void Time::addHr(int h) { hours += h; } void Time::reset(int h, int m) { hours = h; minutes = m; } Time Time::operator+(const Time & t) const { Time result; result.minutes = minutes + t.minutes; result.hours = hours + t.hours +result.minutes / 60; result.minutes %= 60; return result; } void Time::show() const { std::cout << hours << " hours, " << minutes << " minutes"; }
/*usetime0*/ #include <iostream> #include "mytime0.h" int main() { using std::cout; using std::endl; Time planning; Time coding(1, 42); Time fixing(2, 33); Time total; cout << "planning time = "; planning.show(); cout << endl; cout << "coding time = "; coding.show(); cout << endl; cout << "fixing time = "; fixing.show(); cout << endl; total = coding + fixing; //通过运算符+号直接调用重载的运算符 cout << "coding + fixing = "; total.show(); cout << endl; Time morefixing(2, 42); cout << "morefixing time = "; morefixing.show(); cout << endl; total = morefixing.operator+(total);//也可以通过函数名的方式调用 cout << "morefixing.operator+(total) = "; total.show(); cout << endl; return 0; }
总之,operator+()函数名使得可以使用函数表示法或运算符表示法来调用它。
如果t1,t2,t3,t4都是Time对象,可以这样操作吗:
t4 = t1 + t2 +t3;
我们来仔细分析下,+是从左向右结合的运算符,根据上述代码中的函数,上述语句首先被转换为:
t4 = t1.operator+(t2 + t3); //t1调用operator+()函数
接着继续转换为:
t4 = t1.operator+(t2.operator+(t3)); //t2调用operator+()函数
上述语句合法吗?当然合法,因为 t2.operator+(t3)返回一个Time对象,是t2和t3的和,该对象又成为函数调用t1.operator+()的参数,该调用返回t1与表示t2和t3之和的Time对象的和。最后返回值为t1,t2,t3之和,正是我们想要的结果。可以看出,运算符重载实现运算功能要比函数看起来更加自然一些。
三、重载的限制
多数C++运算符都可以用这样的方式重载。但是没有绝对的自由。主要限制有如下几条:
重载后的运算符至少有一个操作数是用户定义的类型。这将防止用户为标准类型重载运算符。假如没有这个限制,我们可以将-重载为两个double相加,而不是它们的差,就乱套了。
使用运算符不能违反运算符原来的句法规则。例如。不能将求模运算符(%)重载成使用一个操作数:% x.同时不能修改运算符的优先级。
不能创建新的运算符。例如,不能定义operator**()函数来表示求幂。
不能重载如下运算符:
sizeof sizeof运算符
. 成员运算符
.* 成员指针运算符
:: 作用域解析运算符
?: 条件运算符
typeid 一个RTTI运算符
const_cast
dynamic_cast
reinterpret_cast
static_cast
5. 大多数运算符都可以通过成员或者非成员函数重载,但是下面的运算符只能通过成员函数重载
= 赋值运算符
() 函数调用运算符
[] 下表运算符
-> 通过指针访问类成员的运算符。
相关文章推荐
- C++学习笔记之运算符重载例子
- 【C++学习笔记】优先级队列以及运算符重载
- 嵌入式开发之C++基础学习笔记5--静态成员,友元,运算符重载,模板,文件流
- c++学习笔记--带有动态空间申请的类成员变量的类的运算符重载
- c++学习笔记 运算符重载
- C++基础学习笔记:运算符重载
- 【C++】【学习笔记】【025-027】运算符重载
- C++学习笔记 lesson5 运算符重载
- C++学习笔记9-运算符重载
- c++学习笔记5:运算符重载、友元和类的类型转换
- C++学习笔记十四-运算符重载
- c++学习笔记(运算符重载)
- C++学习笔记4--静态属性 静态方法 虚方法 抽象方法 多态性 析构函数 运算符重载 多继承 虚继承
- 【菜鸟C++学习笔记】26.运算符重载
- C++学习笔记(运算符重载)
- C++学习笔记(十)运算符重载
- 【C++学习笔记】常见运算符重载
- c++学习笔记--由复数类看运算符重载
- C++学习笔记之运算符重载
- c++学习笔记(三):深拷贝与浅拷贝及等号运算符重载