单目运算符重载和友元

参考链接:https://wenku.baidu.com/view/81f766bba0c7aa00b52acfc789eb172ded6399ac.html?from=search

例1:最经典的复数重载操作

/*当运算符重载为成员函数的时候,运算符的形式参数的个数比运算符规定的参数个数少一个
原因是类的非静态成员函数都有一个隐含的this指针,运算符函数可以用this指针隐式地访问类对象成员,
因此这个对象自身的数据可以直接访问,不需要放在形式参数列表中,少了运算符对象就是表示该对象本身 */
#include <iostream>
using namespace std;

class complex
{
	public:
		complex(double r=0.0,double i=0.0){
			real = r;
			image = i;
		}//构造函数 
		
		//返回类型 operator op(参数类型 参数) 
		complex operator +(complex &c2);//重载运算符"+" 
		complex operator -(complex &c1);//重载运算符"-"
		
		void display()
		{
			cout<<real<<"+"<<image<<"i"<<endl;
		}
	private:
		double image;
		double real;
		
};
//重载函数的实现
//返回类型 类名::operator op(参数类型 参数) 
complex complex::operator +(complex &c2)
{	
	complex c; 
	c.real = real + c2.real;//real实际上就是this->real 
	c.image = image + c2.image;//image实际上就是this->image 
	return c;
	
}
complex complex::operator -(complex &c2)
{
	complex c;
	c.real = real - c2.real;
	c.image = image - c2.image;
	return c;
}
int main()
{
	complex c1(1,2),c2(3,4),c3;
	c3 = c1+c2;c3.display();//4+6i
	c3 = c2-c1;c3.display();//2+2i
	return 0;
}

例2:实现复数的前置++运算

#include <iostream>
using namespace std;

class complex{
	private:
		double real,image;
	public:
		complex(double r=0,double i=0){
			real = r;
			image = i;
		}
		//不传入任何参数,表示该对象本身 
		complex operator ++();
		void display()
		{
			cout<<real<<"+"<<image<<"i"<<endl;
		}
}; 
complex complex::operator ++()
{
	complex c;
	c.image = ++image;//注意这里表示对象的image本身实现了自增 
	c.real = ++real;
	return c;//也可以直接新对象 
}
int main()
{
	complex c1(1,2),c2;
	c2 = ++c1;//将c1自增后赋值给c2,注意重载的++函数返回值是自增后的新对象c 
	c2.display();//2+3i 
	++c1;//注意,这里没有将++c1赋值给任何对象,但是重载的++函数内实现了image和real的自增 
	c1.display();//3+4i 
	return 0;
}

例子3:实现复数的后置++ 运算

#include <iostream>
using namespace std;

class complex
{
	private:
		double image,real;
	public:
		complex(double r=0.0,double i=0.0){
			real = r;
			image = i;
		} 
		/*实现后置++的声明方式为:返回类型 类名 ++(int),这个int的目的就是区分前缀操作符,不起作用*/
		complex operator ++(int);//重载函数声明 
		void display()
		{
			cout<<real<<"+"<<image<<"i"<<endl;
		}
 } ;
 complex complex::operator ++(int)
{
 	complex a;
	a.real = real;
	a.image = image;
	real++;//实现对象数据的自增 
	image++;
	return a;//注意这里的返回值是没有实现自增的 
}
 int main()
 {
 	complex c1(1,2),c2;
 	c2 = c1++;//先赋值给c2然后自增c1 
 	c2.display(); //1+2i,实现了先赋值操作 
 	c1.display();//2+3i,然后又实现了自增 

}
 

例4:重载为友元函数的复数加减法

/*
友元函数是可以直接访问类的私有成员的非成员函数,注意它不是类的成员函数而是定义在类外部的普通函数,
它不属于任何类,但需要在类的定义中加以声明,只需在函数或者类前面添加关键字friend即可
注意:当运算符号定义为友元函数时,因为友元函数不是类的成员函数,所以运算符函数的形式参数的个数
和运算符规定的运算对象个数一致 
*/ 
#include <iostream>
using namespace std;

class complex
{
	public:
		complex(double r=0.0,double i=0.0){
			real = r;
			image = i;
		}
		// 
		friend complex operator +(complex &c1,complex &c2);
		friend complex operator -(complex &c1,complex &c2);
		void display()
		{
			cout<<real<<"+"<<image<<"i"<<endl;
		}
	private:
		double real;
		double image;
 };
 //在类的外部实现重载的友元函数 
 //注意友元函数不是类的成员函数,不需要在实现的时候添加类名,只需要象普通函数定义一样即可 
 complex operator +(complex &c1,complex &c2)
 {
 	complex c;
	c.image = c1.image+c2.image;
	c.real = c1.real;
	return c; 	
 }
complex operator -(complex &c1,complex &c2)
 {
 	complex c;
 	c.real = c1.real-c2.real;
 	c.image = c1.image-c2.image;
 	return c;
 }
 int main()
 {
 	complex c1(1,2),c2(3,4),c3;
 	c3 = c1+c2;
 	c3.display();
 	c3 = c2-c1;
 	c3.display();
 	return 0;
 }

例5:重载为友元函数的前后置的自增

/*
友元函数是可以直接访问类的私有成员的非成员函数,注意它不是类的成员函数而是定义在类外部的普通函数,
它不属于任何类,但需要在类的定义中加以声明,只需在函数或者类前面添加关键字friend即可
注意:当运算符号定义为友元函数时,因为友元函数不是类的成员函数,所以运算符函数的形式参数的个数
和运算符规定的运算对象个数一致 
*/ 
#include <iostream>
using namespace std;

class complex
{
	public:
		complex(double r=0.0,double i=0.0){
			real = r;
			image = i;
		}
		// 
		friend complex operator ++(complex &c1);
		friend complex operator ++(complex &c1,int);
		void display()
		{
			cout<<real<<"+"<<image<<"i"<<endl;
		}
	private:
		double real;
		double image;
 };
 //友元函数不是类的成员函数,参数个数与规定的一致 
 complex operator ++(complex &c1)
 {
 	complex c;
	c1.real++;
	c1.image++;
	c.real = c1.real;
	c.image = c1.image;
	return c; 	
 }
//不要漏掉 int,其实不太明白为什么需要这个int,例3也是 
complex operator ++(complex &c1,int)
 {
 	complex c;
 	c.real = c1.real;
 	c.image = c1.image;
 	c1.real++;
 	c1.image++;
 	return c;
 }
 int main()
 {
 	complex c1(1,2),c2,c3;
 	c2 = ++c1;//c1自增然后赋给c2 
 	c1.display();//2+3i 
 	c2.display();//2+3i
 	c3 = c1++;//先赋值给c3然后自增 
 	c3.display();//2+3i
 	c1.display();//3+4i
 	return 0;
 }

其实这个例子我们可以 将友元函数的参数修改为常引用,也就是如下

friend complex operator ++(const complex &c1);
friend complex operator ++(const complex &c1,int);

会出现错误,提示是一个只读的类型,会导致不能修改自身目标数据,但是在一些特殊的场合我们又需要常引用的参数,这样做的目的是为了不修改传入地址目标对象的数据,这点要注意

参考链接还有很多经典的重载的例子 

猜你喜欢

转载自blog.csdn.net/Li_haiyu/article/details/82052064