操作符重载(operator overloading)是一种形式的C++多态,C++将操作符重载扩展到用户自定义的类型,如允许使用+将两个自定义的对象相加,编译器将根据操作数的数目和类型决定使用那种加法定义。

要重载操作符,需使用操作符函数,格式如下:

operator op (argument-list)

op:要重载的操作符

argument-list: 操作数

操作符函数可以是类的成员函数,也可以是友元函数,如果是类成员函数,则第一个操作数是调用对象,它不在argument-list中。

操作符重载范例,定义一个时间类Time,重载 + - *操作符。

//Time.h

#ifndef TIME_H_
#define TIME_H_
#include <iostream>
class Time
{
public:
Time(void);
Time(int h,int m = );
~Time(void);
void AddMin(int m);
void AddHr(int h);
void Reset(int h = , int m = );
void Show()const;
//重载 +操作符
Time operator+ (const Time & t)const;
Time operator- (const Time & t)const;
// *
Time operator* (double n) const;
//友元函数
friend Time operator* (double n, const Time & t);
//重载<<操作符
friend std::ostream & operator<< (std::ostream & os, const Time & t); private:
int m_hours;
int m_minutes;
};
#endif

//具体实现 Time.cpp

 #include "Time.h"

 Time::Time(void)
:m_hours()
,m_minutes()
{
} Time::Time(int h,int m)
:m_hours(h)
,m_minutes(m)
{
} Time::~Time(void)
{
} void Time:: AddMin(int m)
{
m_minutes += m;
m_hours += m_minutes / ;
m_minutes = m_minutes % ;
}
void Time::AddHr(int h)
{
m_hours += h;
}
void Time::Reset(int h, int m)
{
m_hours = h;
m_minutes = m;
}
void Time::Show()const
{
std::cout << m_hours << ":" << m_minutes;
}
Time Time::operator+ (const Time & t)const
{
Time sum;
sum.m_minutes = m_minutes + t.m_minutes;
sum.m_hours = m_hours + t.m_hours + sum.m_minutes / ;
sum.m_minutes = sum.m_minutes % ;
return sum;
}
Time Time::operator- (const Time & t)const
{
Time diff;
int total1,total2;
total1 = m_minutes + m_hours * ;
total2 = t.m_minutes + t.m_hours * ;
diff.m_hours = (total1 - total2) / ;
diff.m_minutes = (total1 - total2) % ;
return diff;
}
Time Time::operator* (double n) const
{
Time result;
long total_minutes = m_hours * * n + m_minutes * n;
result.m_hours = total_minutes / ;
result.m_minutes = total_minutes % ;
return result;
} Time operator* (double n, const Time & t)
{
Time result;
long total_minutes = t.m_hours * * n + t.m_minutes * n;
result.m_hours = total_minutes / ;
result.m_minutes = total_minutes % ;
return result;
} std::ostream & operator<< (std::ostream & os, const Time & t)
{
os << t.m_hours << ":" << t.m_minutes;
return os;
}
Time operator- (const Time & t)const;
重载减法操作符后,可以很方便对Time对象进行减法运算
Time start_time(10,40);
Time end_time(11,50); Time diff_time = end_time - start_time;
操作符函数为成员函数时,操作符左侧的对象是调用对象,右侧的为参数传递的对象,如上述减法操作实际上等同于:
end_time.operator-(start_time); 关于操作符重载:
1、重载限制
1)重载后的操作符必须至少有一个操作数是自定义类型,主要是防止用户为标准类型重载操作符。
2)使用操作符不能违反操作符原来的句法规则。如 % 是二元操作符,需要两个操作数,不能将它重载成使用一个操作数。
3)不能修改操作符的优先级
4)不能定义新的操作符
5)以下操作符不能重载:
sizeof
.
.*        --成员指针操作符
::
?:         --条件运算符
typeid       --一个RTTI操作符
const_cast    --强制类型转换符
dynamic_cast
reinterpret_cast
static_cast
6)大部分操作符都可以通过成员函数或非成员函数进行重载,但下面的操作符只能通过成员函数重载:
= 赋值操作符
() 函数调用操作符
[] 下标操作符
-> 通过指针访问类成员的操作符 2、通过友元函数重载
对于很多操作符来说,可以选择使用成员函数或非成员函数来实现操作符重载。一般来说非成员函数应该是友元函数,这样才可能直接访问类的私有数据。
如对于Time类的加法操作符: 使用类成员函数重载
Time operator+ (const Time & t)const; 使用非成员函数重载:
friend Time operator+ (const Time & t1, const Time & t2); 对于成员函数版本,一个操作数通过this指针隐式传递,一个通过参数表
友元版本,两个操作数都作为参数来传递
这两种重载方式都能匹配 T1+T2
但在重载操作符中,只能选择其中的一种格式,同时定义被视为二义性错误,导致编译错误。 有些情况必须使用友元来重载
在Time类中,*乘法操作符与其他两种重载的操作符不同,它使用了两种不同的类型,将一个Time值与一个double值结合在一起,这限制了该操作符的使用方式
*使用成员函数重载如下:
Time operator* (double n) const;
意味着只能这样使用该操作符 A = B * 2.5 --> A = B.operator*(2.5) (注:左侧操作数应是调用对象) 如果这样使用将导致编译错误 A = 2.5 * B (左侧操作数是调用对象,而2.5不是对象) 这种情况可以用非成员函数来解决,由于要访问私有数据,故定义为友元函数:
friend Time operator* (double n, const Time & t); 此时,A = 2.5 * B --> A = operator*(2.5,B)
对于非成员重载操作符函数,op左边的操作数对应第一个参数,op右边的操作数对应第二个参数。 创建友元:
a、友元函数的原型应放在类声明中,并加上friend关键字
friend Time operator* (double n, const Time & t);
operator*在类中声明,但不是类的成员函数,但与成员函数具有相同的访问权限 b、在cpp文件中定义函数,由于不是成员函数,故不使用::限定符,也不要在定义中使用friend关键字 总结:类的友元函数是非成员函数,其访问权限与类成员函数相同。 3、常见的友元,重载<<操作符
重载<<操作符,使之能与cout一起来输出对象的内容 原型:
friend std::ostream & operator<< (std::ostream & os, const Time & t);
实现如下:
std::ostream & operator<< (std::ostream & os, const Time & t)
{
    os << t.m_hours << ":" << t.m_minutes;
    return os;
}
如此以来就可以直接输出Time对象
Time t(10.50)
cout << t; 一般来说,要重载<<操作符来显示c_name对象,可使用友元函数,定义如下:
ostream & operator<< (ostream & os, const & c_name obj)
{
  os << ....; //输出对象内容
  return os;
}
之所以要返回ostream的引用,主要作用是可以拼接输出,如 cout << "Current Time:" << t << "\n";

 

C++学习笔记-操作符重载的更多相关文章

  1. RxJava学习笔记(操作符)

    前言 上一篇文章介绍了RxJava的基础知识和简单实现,篇幅已经比较多了,所以把操作符(Operators)相关的内容放在这一篇.有了上一篇文章的基础,相信会比较容易理解操作符相关的内容了. 操作符( ...

  2. C++学习笔记-运算符重载

    运算符重载使得用户自定义的数据以一种更简洁的方式工作 运算符重载规则 重载运算符的限制 可以重载的运算符 + - * / % ^ & | ~ ! = < > += -= *= /= ...

  3. C++ Primer 学习笔记_60_重载操作符与转换 --赋值、下标、成员訪问操作符

    重载操作符与转换 --赋值.下标.成员訪问操作符 一.赋值操作符 类赋值操作符接受类类型形參,通常该形參是对类类型的const引用,但也能够是类类型或对类类型的非const引用.假设未定义这个操作符, ...

  4. C++ Primer 学习笔记_61_重载操作符与转换 --自增/自减操作符

    重载操作符与转换 --自增/自减操作符 引言: 自增,自减操作符常常由诸如迭代器这种类实现,这种类提供相似于指针的行为来訪问序列中的元素.比如,能够定义一个类,该类指向一个数组并为该数组中的元素提供訪 ...

  5. C++ Primer 学习笔记_62_重载操作符与转换 --调用操作符和函数对象

    重载操作符与转换 --调用操作符和函数对象 引言: 能够为类类型的对象重载函数调用操作符:一般为表示操作的类重载调用操作符! struct absInt { int operator() (int v ...

  6. C++ Primer 学习笔记_63_重载运算符和转换 --转换和类类型【上】

    重载运算符和转换 --转换与类类型[上] 引言: 在前面我们提到过:能够用一个实參调用的位 unsignedchar 相同范围的值,即:0到255. 这个类能够捕获下溢和上溢错误,因此使用起来比内置u ...

  7. 高放的c++学习笔记之重载运算与类型转换

    ▲基本概念 (1)重载运算符是具有特殊名字的函数,它们的名字又operator和其后要定义的运算符号共同构成.. (2)对于一个运算符号来说它或者是类的成员,或者至少含有一个类类型的参数. (3)我们 ...

  8. scala学习笔记——操作符

    中置操作符(二元操作符),操作符位于两个参数之间.操作符包括字母,比如to,也可以包括操作符字符,比如1->10,等同于方法调用1.->(10) a 标识符 b 其中的标识符是一个带有两个 ...

  9. C++学习笔记(5)----重载自增自减运算符

    自增运算符“++”和自减运算符“--”分别包含两个版本.即运算符前置形式(如 ++x)和运算符后置形式(如 x++),这两者进行的操作是不一样的.因此,当我们在对这两个运算符进行重载时,就必须区分前置 ...

随机推荐

  1. 假设A.jsp内设定一个<jsp:useBean>元素:

    假设A.jsp内设定一个<jsp:useBean>元素: <jsp:useBean id=”bean1” class=”myBean” /> 下列哪一个为真?(选择1项) A. ...

  2. BestCoder Round #12 War(计算几何)

    War Time Limit: 8000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  3. 利用WM_COPYDATA消息实现进程间通信

    进程间通信最简单的方式就是发送WM_COPYDATA消息,下面通过例子来实现. 发送WM_COPYDATA消息: SendMessage(hRecvWnd, WM_COPYDATA, (WPARAM) ...

  4. MySQL Error: PROCEDURE xmdk.query_all_plan can't return a result set in the given context

    C++调用存储过程失败!出现如下错误:MySQL Error: PROCEDURE xmdk.query_all_plan can't return a result set in the given ...

  5. 让所有IE支持HTML5的解决方案

    自从HTML5能为我们的新网页带来更高效洁净的代码而得到更多的关注,然而唯一能让IE识别那些新元素(如<article>)的途径是使用HTML5 shiv,感谢remy sharp为我们提 ...

  6. DBA面试题及解答

    一:SQL tuning 类 1:列举几种表连接方式答:merge join,hash join,nested loop Hash join散列连接是CBO 做大数据集连接时的常用方式,优化器使用两个 ...

  7. 深入理解JS之Scope链

    JS被很多人认为是『拙劣的语言』,被这门语言里的各种离奇的事情整的团团转,这篇文章主要来讲讲JS中的Scope链,其主要是影响JS中的变量作用域. 注:本文适合稍有一定JS基础的同学 目录: 初步认识 ...

  8. Hadoop日志分析系统启动脚本

    Hadoop日志分析系统启动脚本 #!/bin/bash #Flume日志数据的根文件夹 root_path=/flume #Mapreduce处理后的数据文件夹 process_path=/proc ...

  9. 剑指 offer set 21 圆圈中最后剩下的数字

    思路 1. 经典解法是用环形链表模拟圆圈, 然后每次减少一个节点. 时间复杂度为 o(mn), 空间复杂度为 o(n) 2. 转化成数学问题, 递推公式决定下一个元素. 时间复杂度为 o(n), 空间 ...

  10. 剑指 offer set 17 判断一棵树是否是平衡树

    总结 1. 书上给出一个简洁代码, 说是会重复遍历. 2. 框架相同, 可以写出下面的代码 class Solution { public: bool ans; int getHeight(TreeN ...