对运算符重载

对运算符重载的方法

对运算符的重载实质是函数的重载

重载运算符的函数一般格式:函数类型 operator 运算符名称(形参表){对运算符的重载处理}

//类声明文件
#include<iostream>
using namespace std;
class Complex
{
public:
	Complex(int ,int);
	Complex operator + (const Complex &);
private:
	int real;
	int imag;
};

//类实现文件
#include<iostream>
#include "complex.h"
using namespace std;
Complex::Complex(int r,int i):real(r),imag(i){}
Complex Complex::operator + (const Complex &complex)
{
	this->real += complex.real;
	this->imag += complex.imag;
	return *this;
}

//主函数文件
	class Complex complex(12,25);
	complex = complex+Complex(15,28);

一般将双目运算符重载为友元函数,所以给出下面的代码

//类声明文件
#include<iostream>
using namespace std;
class Complex
{
public:
	Complex();
	Complex(int ,int);
	friend Complex operator + (const Complex &,const Complex &);
private:
	int real;
	int imag;
};

//类实现文件
#include<iostream>
#include "complex.h"
using namespace std;
Complex::Complex():real(0),imag(0){}
Complex::Complex(int r,int i):real(r),imag(i){}
Complex operator + (const Complex &complex1,const Complex &complex2)
{
	
	return Complex(complex1.real+complex2.real,complex1.imag+complex2.imag);
}

//主函数文件
	class Complex complex;
	complex = Complex(15,28)+Complex(15,28);

重载运算符的规则

1、C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载

2、不能重载的运算符有5个:                 .(成员访问运算符)      *(成员指针访问运算符)       ::(域运算符)

                                                                sizeof(长度运算符)     ?:(条件运算符)

      必须类内重载的运算符(属于类成员函数,第一个隐形参数是this指针)

       =(赋值运算符)    [](下标运算符)     ()(函数调用)     ->(成员访问)

3、重载运算符不能改变运算符运算对象(即操作数)的个数,双目运算符是两个操作数,重载后还是两个操作数

4、重载不能改变运算符的优先级别

5、重载不能改变运算符的结合性

6、重载运算符的函数不能有默认参数

7、重载的运算符必须和用户自定义的类型的对象一起使用,其参数至少应该有一个是类对象(或类对象的引用)

8、用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”必须用户重载

      “=”赋值运算符,已经被系统重载过了,除非在指向动态分配内存的指针成员时,否则不需要用户自己在重载

       “&”地址运算符,不必重载,返回对象在内存中的起始地址

9、运算符重载后应该尽量表示原有功能不变,(不要把“>”,重载为小于等等)


运算符重载函数作为类成员函数和友元函数

如果运算符重载函数作为类成员函数,则第一个参数(运算符左侧操作数)必须是本类对象,可以通过this指针(第一个隐形的参数)自由访问本类数据,可以少写一个参数;

如果运算符重载中,运算符左侧的操作数不是本类对象,运算符右侧的操作数是本类对象,但是又想访问本类对象的数据成员,这时不能将运算符重载函数作为类成员函数,这时友元函数上线

C++的一些规则:

 1、=(赋值运算符)    [](下标运算符)     ()(函数调用运算符)     ->(成员运算符) 必须作为成员函数

2、流插入<<和流提取运算符>>、类型转换运算符    不能定义为类成员函数,只能作为友元函数

3、一般将单目运算符和复合运算符重载为成员函数

4、一般将双目运算符重载为友元函数

补充一点知识:

C++引入4种类型转换运算符,更加严格的限制允许的类型转换,使转换过程更加规范:

  • dynamic_cast 用于多态类型的转换
  • static_cast 用于非多态类型的转换
  • const_cast 用于删除const ,volatile 和 __unaligned 属性
  • reinterpret_cast 用于位的简单重新解释
    其中,const_cast和reinterpret_cast的使用会带来更大的风险,因此不到万不得已,不推荐使用

重载双目运算法

双目运算符有两个操作数,一般是友元函数;

//类声明文件
#include<iostream>
using namespace std;
class String
{
public:
	String();
	String(char *);
	friend bool operator > (const String &,const String &);
	friend bool operator < (const String &,const String &);
	friend bool operator == (const String &,const String &);
	friend void compare (const String &,const String &);
	void display();
private:
	char *ptr;
};

//类实现文件
#include<iostream>
#include "string.h"
String::String():ptr(NULL){};
String::String(char *p):ptr(p){};
void String::display()
{
	cout<<ptr;
}
bool operator > (const String &string1,const String &string2)
{
	if(strcmp(string1.ptr,string2.ptr)>0) return true;
	else return false;
}
bool operator < (const String &string1,const String &string2)
{
	if(strcmp(string1.ptr,string2.ptr)<0) return true;
	else return false;
}
bool operator == (const String &string1,const String &string2)
{
	if(strcmp(string1.ptr,string2.ptr)==0) return true;
	else return false;

}
void compare (const String &string1,const String &string2)
{
	if((string1 == string2)>0)
	{
		cout<<string1.ptr;
		cout<<"等于";
		cout<<string2.ptr;
		cout<<endl;
	}
	if((string1 > string2)>0)
	{
		cout<<string1.ptr;
		cout<<"大于";
		cout<<string2.ptr;
		cout<<endl;
	}
	if((string1 < string2)>0)
	{
		cout<<string1.ptr;
		cout<<"小于";
		cout<<string2.ptr;
		cout<<endl;
	}
}

//主函数文件
	class String string1("dashaguan");
	class String string2("dabendan");
	class String string3("dabendan");
	compare(string1,string2);
	compare(string2,string3);


重载单目运算符

单目运算符只有一个操作数,因此运算符重载函数之后一个参数,如果运算符重载函数作为成员函数,则可省略。

在自增(减)运算符重载函数中,增加一个int型形参(仅仅是为了 区分)就是后置自增(减)运算符函数

//类声明文件
#include<iostream>
using namespace std;
class Time
{
public:
	Time();
	Time(int ,int );
	Time operator ++();
	Time operator ++(int);
	void display();
private:
	int min;
	int sec;

};

//类实现文件
#include<iostream>
#include "time.h"
using namespace std;
Time::Time():min(0),sec(0){};
Time::Time(int m,int s):min(m),sec(s){};
Time Time::operator ++()//前++
{
	if(++this->sec == 60)
	{
		++this->min;
		this->sec = 0;
	}
	return *this;
}
Time Time::operator ++(int)//后++
{
	Time temp(*this);
	if(++this->sec == 60)
	{
		++this->min;
		this->sec = 0;
	}
	return temp;
}

void Time::display()
{
	cout<<this->min<<":"<<this->sec<<endl;
}


//主函数文件
	class Time time1(5,59);
	time1.display();
	++time1;
	time1.display();
	cout<<"------------------------"<<endl;
	class Time time2 = time1++;
	time1.display();
	time2.display();



重载流插入运算符和流提取运算符

只能将重载“<<”和“>>”函数作为友元函数,而不能将他们定义位成员函数

//类声明函数
#include<iostream>
using namespace std;
class Complex
{
public:
	Complex();
	Complex(int ,int);
	friend Complex operator + (const Complex &,const Complex &);
	friend ostream& operator << (ostream&,const Complex &);
	friend istream& operator >> (istream&, Complex &);
private:
	int real;
	int imag;
};

//类实现文件
#include<iostream>
#include<cmath>
#include "complex.h"
using namespace std;
Complex::Complex():real(0),imag(0){}
Complex::Complex(int r,int i):real(r),imag(i){}
Complex operator + (const Complex &complex1,const Complex &complex2)
{
	
	return Complex(complex1.real+complex2.real,complex1.imag+complex2.imag);
}
ostream& operator << (ostream &output,const Complex &complex)
{
	cout<<complex.real;
	if(complex.imag>0)
		cout<<" + "<<complex.imag<<"i";
	else
		cout<<" - "<<abs(complex.imag)<<"i";

	return output;

}
istream& operator >> (istream &input, Complex &complex)
{
	cin>>complex.real>>complex.imag;
	return input;

}
//主函数文件
	class Complex complex1;
	complex1 = Complex(15,28)+Complex(15,28);
	cout<<complex1<<endl;
	class Complex complex2;
	cin>>complex2;
	cout<<complex2<<endl;


不同类型数据间的转换

1、标准类型数据间的转化

       类型名 (数据)           e.g. int(17.5)

2、用转换构造函数进行不同类型数据的转换

       转换构造函数:将一个其他类型的数据转换成一个类的对象。

       e.g. Complex(12.5)

        类Complex中全部都是int,但是这时出现了double。首先将double转变为int,然后赋值为real或者imag,与之对应另一个    imag或real赋值为0;下面代码给出的解释(只能出现一个,我只不过是没有注释)

Complex::Complex(double d):real(d),imag(0){};
Complex::Complex(double d):real(0),imag(d){};

注意:转换构造函数只能有一个参数,如果多个参数,就不是转换构造函数

//类声明文件
#include<iostream>
using namespace std;
class Complex
{
public:
	Complex();
	Complex(double );
	Complex(int ,int );
	friend Complex operator + (const Complex &,const Complex &);
	void display();
private:
	int real;
	int imag;
};

//类实现文件
#include<iostream>
#include "complex.h"
using namespace std;
Complex::Complex():real(0),imag(0){}
Complex::Complex(double d):real(d),imag(0){};
Complex::Complex(double d):real(0),imag(d){};
Complex::Complex(int r,int i):real(r),imag(i){}
Complex operator + (const Complex &complex1,const Complex &complex2)
{
	
	return Complex(complex1.real+complex2.real,complex1.imag+complex2.imag);
}
void Complex::display()
{
	cout<<this->real<<" + "<<this->imag<<"i"<<endl;
}

//主函数文件
	class Complex complex;
	complex = Complex(15,28)+Complex(15,28);
	complex = Complex(15.8,28)+Complex(15.0);
	complex.display();

不仅可以将一个标准类型数据转换成类对象,也可以将另一个类的对象转换成转换构造函数所在的类对象。

例如:将一个学生类对象转换为教师类对象(毕业以后当老师),要求把学生的编号,姓名,性别复制到一个教师类中。

Teacher(Student &s){num = s.num;strcpy(name,s.name);sex = s.sex;}

3、类型转换函数

        operator 类型名 () {类型转换语句}     

        一般会添加const,可以保证对象不被修改,同时也可以得到相应的返回值      operator 类型名 () const  {类型转换语句}

        在函数名前面不能指定函数类型,函数没有参数。

        类型转换函数只能作为成员函数,因为转换的主体是本类的对象。不能作为友元函数或普通函数。

         当有了相应的转换构造函数情况下,将运算符“+”函数重载为友元函数,在进行两个负数相加时,可以用交换律

         如果将运算符“+”函数重载类成员函数,则交换律不适用。

         实例代码(最后三行实现了加法的交换律)

//类声明文件
#include<iostream>
using namespace std;
class Complex
{
public:
	//构造函数
	Complex();                                                   
	//转换构造函数,只有一个形参
	Complex(double );
	//构造构造函数
	Complex(int ,int );
	//运算符重载函数
	friend Complex operator + (const Complex &,const Complex &);
	void display();
private:
	int real;
	int imag;
};

//类实现文件
#include<iostream>
#include "complex.h"
using namespace std;
Complex::Complex():real(0),imag(0){}
Complex::Complex(double d):real(d),imag(0){};
//Complex::Complex(double d):real(0),imag(d){};
Complex::Complex(int r,int i):real(r),imag(i){}
Complex operator + (const Complex &complex1,const Complex &complex2)
{
	
	return Complex(complex1.real+complex2.real,complex1.imag+complex2.imag);
}

void Complex::display()
{
	cout<<this->real<<" + "<<this->imag<<"i"<<endl;
}

//主函数文件
	class Complex complex1(3,30),complex3;
	complex3 = complex1 + 2.5;
	complex3 = 10 + complex1;

如果在上述函数中添加了类型转换函数,容易造成二义性。

转换构造函数运算符“+”重载函数)与 类型转换函数造成了二义性。

上述的代码中complex3 = 10 + complex1;有两种解释

第一种解释:将10采用转换构造函数变成Complex对象,然后调用运算符“+”重载函数,实现对象的加法

第二种解释:将complex1采用类型转换函数变成int,然后实现整型数据的加法。

发布了114 篇原创文章 · 获赞 28 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/ChaoFeiLi/article/details/103644130