声明:部分文字资源来源于其他博文,地址是http://blog.csdn.net/jnu_simba/article/details/9292221
另外:如果你没有C++基础,建议先看博主的另一篇博文 《C++类、对象、继承、派生类基础教程》
接着之前的C++基础知识,这里对C++操作符重载,友元基础教程做了一个总结,这些概念虽然很小,但是,作为一名初学者或者说以后想深入学习软件方向的人来说,必须要把基础学好。文中如果有错误的地方,还望指正。
一、C++中操作符重载
之前已经介绍了,函数重载,C++中还有一个叫做操作符重载。它是C++多态下产生的一种思想,让操作符也可以和普通的“+” “-” “*” “/”一样能够用在对象和对象之间,比如如果我们采用了“+”重载,就可以实现,两个对象之间直接相加,让客户能够直接使用OOP,而无须关注重载内部是如何实现的,这点可以说明操作符重载完全符合C++特性,以至于,我们更加深入理解了为什么C++叫做面向对象的编程。
下面对普通的相加和操作符重载相加做一次对比,代码如下:
void Time::AddHr(int h) { hours += h; }
Time Time::operator+(Time &t) { Time sum; sum.minutes = minutes + t.minutes; sum.hours = hours + t.hours + sum.minutes / 60; sum.minutes %= 60; return sum; }
可见,格式应该为 operator+()重载“ + ”操作符,这个操作符分为一元操作符和二元操作符。
一元操作符:一些只需要一个操作数的运算符称为一元运算符。一元运算符有:"sizeof",'+'——正号,'-'——负号,'!', '++', '--' , '~'——位非,返回数字的非。
二元操作符:运算所需变量为两个的运算符叫做双目运算符·或者要求运算对象的个数是2的运算符称为双目运算符。
更多的一元操作符和二元操作符,可以看相关资料
通过这个例子可以看出,其实操作符重载是函数重载的一种,或者是特殊情况。
二、分类
操作符重载的表现方法有两种:
一是成员函数重载,也就是,操作符重载函数是放在类里面的或者属于内联函数。
Time Time::operator+(Time &t) { Time sum; sum.minutes = minutes + t.minutes; sum.hours = hours + t.hours + sum.minutes / 60; sum.minutes %= 60; return sum; }
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; Time operator+(Time &t); Time operator-(Time &t); Time operator*(double n); friend Time operator* (double m, Time &t) { return t * m; } friend std::ostream & operator<< (std:: ostream &os, const Time &t); void Show()const; };
第二就是如代码中所示:Time operator+(Time &t)这条语句在class内部,而且并且属于成员函数,但是,后面的friend Time operator语句是加了friend,叫做友元函数。
为什么要这样去写呢,后面会对友元函数做一些介绍,介绍友元函数的方便之处。
总之,有两种方式:
成员函数原型的格式:
声明 :函数类型 operator 运算符(参数表); [具体可以参考我的代码声明]
定义:成员函数定义的格式:
函数类型 类名::operator 运算符(参数表)
{
函数体;
}
友元函数原型格式:
友元函数原型的格式:
friend 函数类型 operator 运算符(参数表);
友元函数定义的格式:
函数类型 类名::operator 运算符(参数表)
{
函数体;
}
两种的区别是:友元函数所有的参数是显式的,成员函数的参数有部分是隐式的。如果说不是友元函数是无法访问类中成员,但是,友元函数虽然是非成员函数,但是可以访问类中的成员,关于它的安全性,日后在做介绍。
三、重载的限制
并不是每一个符号都可以重载,比如
作用域解析运算符 ::
条件运算符 ? :
直接成员访问运算符 .
类成员指针引用的运算符 .*
sizeof运算符 sizeof
这里就不一一列举了,实在是原则太多了,建议翻阅<c++ primer plus>详细查阅
四、操作符重载的选择
一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
五、下面吧完整的测试代码贴上。
头文件:
#ifndef MYTIME0_H_ #define MYTHIME0_H_ #include "iostream" 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; Time operator+(Time &t); Time operator-(Time &t); Time operator*(double n); friend Time operator* (double m, Time &t) { return t * m; } friend std::ostream & operator<< (std:: ostream &os, const Time &t); void Show()const; }; #endif函数定义文件:
#include "iostream" #include "mytime0.h" using namespace std; 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+(Time &t) { Time sum; sum.minutes = minutes + t.minutes; sum.hours = hours + t.hours + sum.minutes / 60; sum.minutes %= 60; return sum; } Time Time::operator-(Time &t) { Time diff; int tot1, tot2; tot1 = t.minutes + 60 * t.hours; tot2 = minutes + 60 * hours; diff.minutes = (tot2 - tot1) % 60; diff.hours = (tot2 - tot1) / 60; return diff; } Time Time::operator*(double mult) { Time result; long totalmimutes = hours * 60 + minutes*mult; result.hours = totalmimutes / 60; result.minutes = totalmimutes % 60; return result; } void Time::Show()const { cout << "hours: " << hours << "minutes: " << minutes << endl; } std::ostream & operator<< (std::ostream &os, const Time &t) { os << t.hours << " hours" << t.minutes << " minutes"; return os; }
#include "iostream" #include "mytime0.h" using namespace std; int main() { Time aida(3, 35); Time tosca(2, 48); Time temp; cout << "Aida and Tosca:" << endl; cout << aida << "\n" << tosca << endl; temp = aida + tosca; cout << "Aida + Tosca" << temp << endl; temp = aida * 1.17; cout << "Aida * 1.17" << temp << endl; cout << "10 * Tosca:" << 10 * tosca << endl; return 0; }为了便于大家理解,我又单独写了一个友元函数。
在类里面写友元函数[内联]
friend Time operator+(Time &a, Time &b) { Time end; end.hours = a.hours + b.hours; end.minutes = a.minutes + b.minutes; return end; }
int main() { Time aida(3, 35); Time tosca(2, 48); Time temp; cout << "Aida and Tosca:" << endl; cout << aida << "\n" << tosca << endl; temp = aida + tosca + tosca; cout << "Aida + Tosca + Tosca" << temp << endl; temp = aida * 1.17; cout << "Aida * 1.17" << temp << endl; cout << "10 * Tosca:" << 10 * tosca << endl; return 0; }
temp中的值,已经实现了三个对象的直接相加,这种思想在多个分离的业务实现累加时候会很有帮助,不必为每一次累加写方法去实现,通过重载就实现了一个较大集合的累加,是一个很棒的Idear~
虽然这些都是很小的东西,很细节的东西,不过,建议初学者,一定要搞清楚,不然去面阿里、鹅厂,就坐等被秒。