C++操作符重载 友元基础教程

声明:部分文字资源来源于其他博文,地址是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~

虽然这些都是很小的东西,很细节的东西,不过,建议初学者,一定要搞清楚,不然去面阿里、鹅厂,就坐等被秒。







你可能感兴趣的:(C++,面向对象,软件开发,友元,操作符重载)