C++基础 学习笔记五:重载之运算符重载

C++基础 学习笔记五:重载之运算符重载

什么是运算符重载

用同一个运算符完成不一样的功能即同一个运算符能够有不一样的功能的方法叫作运算符重载。运算符重载是静态多态性的体现。ios

运算符重载的规则

  1. 重载公式

返回值类型 operator 运算符名称 (形参表列){}数组

  1. 可以重载的运算符

    + - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> <<= >>= == != <= >= && || ++ -- , ->* -> () [] new new[] delete delete[]函数

  2. 不能重载的运算符

    sizeof: ?.::学习

  3. 重载不能改变运算符的优先级和结合性

  4. 重载不会改变运算符的用法

  5. 运算符重载函数不能有默认的参数

  6. 重载后的运算符必须至少有一个操做数是用户自定义的类型,以此来防止为标准类型重载运算符。

  7. 特殊的运算符

    ->[ ]( )=只能以成员函数的形式重载测试

运算符重载的实现原理

以运算符做为名称的函数称之为运算符函数。这种重载称为运算符重载。this

具体实现(以运算符+ -为例)

1. 在全局范围内重载运算符

Complex operator+(const Complex &leftArg, const Complex &rightArg)
{
	return Complex(leftArg.real+rightArg.real,leftArg.imag+rightArg.imag);
}
Complex sum = leftArg + rightArg;

第五行调用函数operator+,而且将leftArgleftArg做为符号函数的参数,返回值赋值给sum,等同于sum = operator+(leftArg,rightArg);spa

2.在类中重载运算符

class Complex
{
public:
	Complex operator-(const Complex & arg)
	{
		return Complex(this.real - arg.real, this.imag - arg.imag);
	}
};
Complex diff = leftArg - rightArg;

第九行调用函数operator-,而且将leftArg做为符号函数的参数,返回值赋值给diff,等同于diff = leftArg.operator-(rightArg);code

运算符重载的使用例子

#include<iostream>
#include<string>

using namespace std;

enum complePart
{
	real = 0,
	imag
};

class Complex
{
	public:
		int real;
		int imag;
	public:
		Complex() : real(0),imag(0){}
		Complex(int r, int i) : real(r),imag(i){}
		Complex operator-(const Complex & arg)// +,-,*,/ 这四个运算符重载方法同样
		{
			return Complex(this->real - arg.real, imag - arg.imag);
		}
		friend Complex operator*(const Complex &leftArg, const Complex &rightArg);//友元函数
		bool operator==(const Complex &arg)// ==,!=  这两个个运算符重载方法同样
		{
			if(this->real == arg.real && this->imag == arg.imag)
				return true;
			else
				return false;
		}
		Complex& operator+=(const Complex &arg)// +=,-=,*=,/= 这四个运算符重载方法同样
		{
			this->real += arg.real;
			this->imag += arg.imag;
			return *this;
		}
		friend istream& operator>>(istream &input, Complex &complex);
		friend ostream& operator<<(ostream &output, Complex &complex);
		Complex& operator++()// ++i,--i  这两个个运算符重载方法同样
		{
			++this->real;
			++this->imag;
			return *this;
		}
		Complex operator++(int i)// i++,i--  这两个个运算符重载方法同样
		{
			Complex tempComplex = *this;
			++this->real;
			++this->imag;
			return tempComplex;
		}
		void* operator new(size_t size)
		{
			cout << "call function void* operator new(size_t size)" << endl;
			void* pointer = malloc(size);
			return pointer;
		}
		void operator delete(void* pointer)
		{
			cout << "call function void operator delete(void* pointer)" << endl;
			free(pointer);
		}
		void* operator new[](size_t size)
		{
			cout << "call function void* operator new[](size_t size)" << endl;
			void* pointer = malloc(size);
			return pointer;
		}
		void operator delete[](void* pointer)
		{
			cout << "call function void operator delete[](void* pointer)" << endl;
			free(pointer);
		}
		void* operator new(size_t size,Complex* complex,int step)//placement new
		{
			cout << "call function void* operator new(size_t size,Complex* complex,int step)" << endl;
			return complex + step;
		}
		operator int()
		{
			return this->real;
		}//c->operator int()
		int& operator [](int i)
		{
			int errorValue = 0;
			if(i == 0)
				return this->real;
			else//为了演示不要在乎 
				return this->imag;
		}
		const int& operator[](int i) const
		{
			cout << "call function const int& operator[](int i) const" << endl;
			if(i == 0)
				return this->real;
			else//为了演示不要在乎 
				return this->imag;
		}
};

Complex operator+(const Complex &leftArg, const Complex &rightArg)//全局重载 
{
	return Complex(leftArg.real+rightArg.real,leftArg.imag+rightArg.imag);
}
istream& operator>>(istream &input, Complex &complex)
{
	input >> complex.real >> complex.imag;
	return input;
}
ostream& operator<<(ostream &output, Complex &complex)
{
	output << complex.real << " " << complex.imag << " ";
	return output;
}
Complex operator*(const Complex &leftArg, const Complex &rightArg)
{
	return Complex((leftArg.real * rightArg.real) - (leftArg.imag * rightArg.imag),
	(leftArg.imag * rightArg.real) - (leftArg.real * rightArg.imag));
}

int main()
{
	Complex leftArg(2,2);
	Complex rightArg;
	cin >> rightArg;//输入3,3
	Complex result = leftArg + rightArg;
	cout << result << endl;
	result = leftArg - rightArg;
	cout << result << endl;
	result = leftArg * rightArg;
	cout << result << endl;
	string str = (leftArg == rightArg)?"true":"false";
	cout << str << endl;
	result += leftArg;
	cout << result << endl;
	cout << ++result << endl;
	Complex resulttttt = result++;
	cout << resulttttt << endl;
	cout << result << endl;
	Complex* pointer = new Complex(1,1);
	cout << *pointer << endl;
	delete pointer;
	Complex* pointerArray = new Complex[10];
	cout << pointerArray[2] << endl;
	new(pointerArray, 2)Complex(123,321);//placement new
	cout << pointerArray[2] << endl;
	cout << (int)pointerArray[2] << endl;
	cout << pointerArray[2][complePart::real] << endl;
	cout << pointerArray[2][complePart::imag] << endl;
	delete[] pointerArray;
	const Complex c_result(111,222);
	cout << c_result[complePart::imag] << endl;
	
    return 0;
}
/* 运行结果为: 
3 3
5 5
-1 -1
0 0
false
2 2
3 3
3 3
4 4
call function void* operator new(size_t size)
1 1
call function void operator delete(void* pointer)
call function void* operator new[](size_t size)
0 0
call function void* operator new(size_t size,Complex* complex,int step)
123 321
123
123
321
call function void operator delete[](void* pointer)
call function const int& operator[](int i) const
222

--------------------------------
Process exited after 3.063 seconds with return value 0
请按任意键继续. . .
*/

代码分析

1.双目运算符

+-*/%这五个运算符均为双目运算符,重载方法相同。重载例子详见第20、2四、10二、116行,其中第102行的+重载函数为全局重载,测试详见第12七、12九、131行。对象

2.关系运算符

==!=<><=>=这六个运算符均为关系运算符,重载方法相同。重载例子详见第25行,测试详见第133行。内存

3.自增自减运算符

++--这两个运算符均为自增自减运算符,因为运算符的特殊性,运算符又分为前置和后置形式。重载方法两种形式不一样,可是相同形式的重载方法相同。重载例子详见第40、46行,测试详见第13七、138行。

4.空间申请与释放运算符

newdeletenew[]delete[]这四个运算符均为空间申请与释放运算符,重载方法类似。重载例子详见第5三、5九、6四、70行,测试详见第14一、14三、14四、151行。在重载空间申请运算符时除newnew[]这两种方式外还有一种方式叫作placement new。重载例子详见第75行,测试详见第146行。

placement new

一般new操做分两步:

  1. 分配内存。
  2. 若为类则调用类的构造函数建立对象。

可是若已分配好内存如:Complex* pointerArray = new Complex[10];,若要在pointerArray[2]分配的内存上建立对象则须要用placement new来完成该操做。操做以下:new(pointerArray, 2)Complex(123,321);,完成该操做后pointerArray[2]中的复数对象将会变为123+321i

5.输入和输出运算符

>><<这两个运算符均为输入和输出运算符,重载方法类似。能够将输出运算符<<和输入运算符>>看做是C++对左移运算符<<和右移运算符>>分别进行了重载,但只能输出输入标准类型。重载例子详见第3八、39行,测试详见第12六、128行。

6.其它运算符

  1. (数据类型)运算符

    (数据类型)是强制类型转换运算符,能够将对象转换为相应的类型。

  2. []运算符

    []是下标运算符,能够将对象转换为相似数组,能够经过下标操纵对象。

重载运算符的形式

1.以成员函数重载运算符

成员函数重载只容许右参数的隐式转换,通常单目运算符以成员函数重载。只能重载为成员函数的运算符:=()[]->等。

2.以全局函数(友元函数)重载运算符

友元函数重载可以接受左参数和右参数的隐式转换,友员函数重载运算符经常使用于运算符的左右操做数类型不一样的状况。通常双目运算符以友元函数重载。只能重载为友元函数的运算符:<<>>等。

相关文章
相关标签/搜索