C++运算符重载详解

    xiaoxiao2021-12-14  18

    重载运算符的两种形式: 重载运算符有两种方式,即: 重载为类的成员函数||重载为类的非成员函数。 重载为类的非成员函数的时候: 通常我们都将其声明为友元函数,因为大多数时候重载运算符要访问类的私有数据,(当然也可以设置为非友元非类的成员函数。但是非友元又不是类的成员函数是没有办法直接访问类的私有数据的),如果不声明为类的友元函数,而是通过在此函数中调用类的公有函数来访问私有数据会降低性能。所以一般都会设置为类的友元函数,这样我们就可以在此非成员函数中访问类中的数据了。

    有一个时间类,我们要进行的任务是对时间类的加减乘。或许你会觉得很简单,简单就对了,因为这更容易让你深入的理解到这二者

    MyTime.h文件:

    #pragma once #ifndef MYTIME_H_ #define MYTIME_H_ class CMyTime { private: int m_hours; int m_minutes; public: CMyTime(); CMyTime(int h, int m = 0); void AddHr(int h); //小时更改 void AddMin(int m);//分钟更改 void Reset(int h = 0, int m = 0); //重新设置时间 CMyTime operator+(const CMyTime &t) const; //重载加法 CMyTime operator-(const CMyTime &t) const; //重载减法 CMyTime operator*(double n) const; //重载乘法 void Show() const; ~CMyTime(); }; #endif

    MyTIme.cpp文件:

    #include "stdafx.h" #include "MyTime.h" #include <iostream> CMyTime::CMyTime() { m_hours = 0; m_minutes = 0; } CMyTime::CMyTime(int h, int m) { m_hours = h; m_minutes = m; } CMyTime::~CMyTime() { } void CMyTime::AddHr(int h) //小时更改 { m_hours += h; } void CMyTime::AddMin(int m) //分钟更改 { m_minutes = m; } void CMyTime::Reset(int h, int m) //重新设置时间 { m_hours = h; m_minutes = m; } CMyTime CMyTime::operator+(const CMyTime &t) const //重载加法运算符函数 { CMyTime sum; sum.m_minutes = t.m_minutes + m_minutes; sum.m_hours = t.m_hours + m_hours + sum.m_minutes / 60; sum.m_minutes %= 60; return sum; } CMyTime CMyTime::operator-(const CMyTime &t) const //重载为减法运算符函数 { CMyTime diff; int tot1, tot2; tot1 = t.m_minutes + 60 * t.m_hours; tot2 = m_minutes + 60 * m_minutes; diff.m_minutes = (tot2 - tot1) % 60; diff.m_hours = (tot2 - tot1) / 60; return diff; } CMyTime CMyTime::operator*(double n) const //重载为乘法运算符函数。 { CMyTime result; long totalMinutes = m_hours * 60 * n+ m_minutes *n; result.m_minutes = totalMinutes % 60; result.m_hours = totalMinutes / 60; return result; } void CMyTime::Show() const { std::cout << m_hours << " hours " << m_minutes << " minutes\n"; }

    主函数:

    // Study11-02.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include "MyTime.h" int _tmain(int argc, _TCHAR* argv[]) { using std::cout; using std::endl; CMyTime weeding(4, 35); CMyTime waxing(2, 47); CMyTime total; CMyTime diff; CMyTime adjusted; cout << "weeding Time = "; weeding.Show(); cout << endl; cout << "waxing Time = "; waxing.Show(); cout << endl; cout << "total work Time = "; //(1) total = weeding + waxing; total.Show(); cout << endl; diff = weeding - waxing; cout << "weeding Time - waxing Time = "; //(2) diff.Show(); cout << endl; adjusted = total *1.5; //(3) cout << "adjusted work Time = "; adjusted.Show(); cout << endl; return 0; }

    在主函数中,我们创建了weeding 和waxing连个对象,进行了操作。那么现在问题来了。 我们看(3)标记处,现在adjusted = total *1.5; 是可以运行的,那么**adjusted = 1.5*total可以运行吗? 答案当然是不可以,我们还原下此语句:adjusted = total.operator*(1.5),换成1.5在乘号前面当然是不可以的。因为1.5不是对象。

    这个时候有两种解决方式: 一:告诉每个人只能按照adjusted = total *1.5; 这种方式来,这种方式看起来当然是欠缺的。那么重头戏来了: 二:非成员函数,声明为 CMyTime operator *(double m,const CMyTime &t); 这样等价于:A = operator * (1.5,B)等价于:A = 1.5 * B;出于性能考虑,我们将其声明为friend 即友元函数(前面已经解释过为什么要声明为友元了): friend CMyTime operator*(double m,const CMyTime &t);

    接下来我们这样做:在上面的MyTIme.h文件的public中加入:friend CMyTime operator*(double m, const CMyTime &t){ return t*m; } (因为这个函数操作很简单,可以直接为内联函数);然后就可以运行 A = 1.5 * B语句了。

    接下来我们为了更好的了解重载运算符,来进行<<运算符的重载:

    cout 《adjusted; 这句话能直接执行输出,(显然这种输出方式如果不重载<<运算符是没有办法执行的。因为cout根本不知道输出adjusted的什么东西),对于<<的重载我们有两种版本: 第一种声明为成员函数: 照葫芦画瓢:CMyTime operator<<(ostream &s); 那么这种生命方式会造成什么结果呢? 答案是:输出会变成:adjusted<< cout;或许看起来很不好,但这确实是正确的。 因为这等价于:adjusted.operator<<(cout);

    第二种版本:(也是更好的版本): MyTIme.h 声明: friend void operator<<(ostream &os,const CMyTime &t); MyTime.cpp实现: void operator<<(ostream &os,const CMyTime &t) { os << t.hours << t.minutes }; 这样就可以执行cout << adjusted 这条语句了。

    重要的问题来了,我们什么时候声明为成员函数,什么时候声明为非成员函数呢? 首先,我们要明白这句话:对于成员函数来说,一个操作数通过this指针隐式的传递,(即本身),另一个操作数作为函数的参数显示的传递;对于友元函数(非成员函数)两个操作数都是通过参数来传递的。 (1)一般来说,弹幕运算符重载为类的成员函数,双目运算符重载为类的友元函数(咳咳,一般情况下) (2)双目运算符不能将 = 。 ()【】。-> 重载为类的友元函数。 (3)如果运算符的第一次操作数要求为隐式转换则必须为友元函数。 (4)当最左边的要求为类对象,而右边的是一个内置类型,则要为友元函数。

    最重要的注意点: **T1 = T2 + T3; 可以为T1 = T2.operator+(T3); 也可以为T1 = operator+(T2,T3); 但是这两种方式不能同时声明定义,因为这会出现二义性。造成程序不知道该执行那个函数。在进行运算符重载的时候千万要注意造成二义性的情况。**

    原网址 http://blog.csdn.net/lishuzhai/article/details/50781753

    转载请注明原文地址: https://ju.6miu.com/read-969155.html

    最新回复(0)