Twelve 类运算符重载

原文链接(点击原文链接获取更多学习干货):

Twelve 类运算符重载 – 布尔博客Twelve 类运算符重载http://blog.bools.cn/archives/1640

1.加号运算符重载

如果想要自定义类型进行加减操作,需要编写函数来进行重载。在成员函数或全局函数中写函数

函数名operator+(){}

1.成员函数的加号重载

class person
{
public:
	person() {};
	person(int a, int b) :m_A(a), m_B(b) 
	{};
	加号运算符重载,成员函数
	person operator+(person& p)
	{
		person temp;
		temp.m_A = this->m_A + p.m_A;
		temp.m_B = this->m_B + p.m_B;
		return temp;
	}
	int m_A;
	int m_B;
};
void test01()
{
	person p1(10, 20);
	person p2(20, 30);
	person p3 = p1 + p2;
	person p4 = p3.operator+(p2);//两个一样的作用,就是将加号重载,类成员函数的加号运算符
	cout << "p3是p1和p2加之后:m_A:" << p3.m_A << "  m_B:" << p3.m_B << endl;
	cout << "p4是p4和p2加之后:m_A:" << p4.m_A << "  m_B:" << p4.m_B << endl;

}

成员函数里面的函数加号重载实现方法有两种

person p3 = p1 + p2;
person p4 = p3.operator+(p2);//两个一样的作用,就是将加号重载,类成员函数的加号运算符

直接加减或者使用类里面的函数。

2.全局函数的加号重载

class person
{
public:
	person() {};
	person(int a, int b) :m_A(a), m_B(b) 
	{};
	int m_A;
	int m_B;
};
//利用全局函数来进行加号运算符的重载
person operator+(person& p1, person& p2)
{
	person temp;
	temp.m_A = p1.m_A + p2.m_A;
	temp.m_B = p1.m_B + p2.m_B;
	return temp;
}
void test01()
{
	person p1(10, 20);
	person p2(20, 30);
	person p3 = p1 + p2;
	person p4 = operator+(p2, p3);//全局函数的加号重载
	cout << "p3是p1和p2加之后:m_A:" << p3.m_A << "  m_B:" << p3.m_B << endl;
	cout << "p4是p4和p2加之后:m_A:" << p4.m_A << "  m_B:" << p4.m_B << endl;

}

全局函数的加号重载也可以直接用加号+,也可以像用函数一样

	person p3 = p1 + p2;
	person p4 = operator+(p2, p3);//全局函数的加号重载

2.左移运算符重载

一般看到的都是普通的左移运算符,常用在cout<<中,而只能识别编译器默认的数据类型,如果想要输出自定义数据类型,就要重载左移运算符。

而和加号重载运算符不一样,左移重载运算符不能写在成员函数里面。

例子:

class person
{
public:
	person() {};
	person(int a, int b)
	{
		m_A = a;
		m_B = b;
	}
	int m_A ;
	int m_B;

};
ostream& operator<<(ostream& cout, person& p)
{
	cout << "m_A:" << p.m_A << "  m_B:" << p.m_B;
	return cout;
}
void test01()
{
	person p1(10,20);
	cout << p1 << endl;
}

在例子当中,我们看到,因为cout属于ostream的类似于数据类型当中,所以调用的时候调用参数类型是ostream,而返回值也是ostream类型。

3.前置后置递增运算符重载

前置后置递增运算符和前面两个一样,也是对自定义的运算符的一种重载。

就是像i++或者++i、i--或者--i一样。

前置++

先++,再返回对象。

class MyInteger
{
	friend ostream& operator<<(ostream& cout, MyInteger& myint);

public:
	MyInteger()
	{
		m_Num = 0;
	};
	//前置重载
	MyInteger& operator++()
	{
		//直接++,返回的是对象
		this->m_Num++;
		return *this;
	}
private:
	int m_Num;
};
ostream& operator<<(ostream& cout, MyInteger& myint)
{
	cout << myint.m_Num;
	return cout;
}
void test01()
{
	MyInteger myint;
	cout << ++myint << endl;
}

前置后置增函数都是成员函数,而因为在输出时cout了自定义的数据类型,所以还要进行一次左移符号重载。

后置++

先保存一个临时值,再++。

class MyInteger
{
	friend ostream& operator<<(ostream& cout, MyInteger& myint);

public:
	MyInteger()
	{
		m_Num = 0;
	};
	//后置重载
	MyInteger& operator++(int)
	{
		//用一个临时变量保存先
		MyInteger temp = *this;
		m_Num++;
		return temp;
	}
private:
	int m_Num;
};
ostream& operator<<(ostream& cout, MyInteger& myint)
{
	cout << myint.m_Num;
	return cout;
}
void test01()
{
	MyInteger myint;
	cout << myint++ << endl;
}

后置函数重载的话需要先将对象的值保存,然后++。

而在使用前置或者后置时,优先考虑使用前置

这里需要注意:返回值用引用的时候返回的是对象,而不用引用的时候返回的只是值而已。

4.指针运算符的重载(智能指针)

智能指针

意思就是将开辟的堆空间的指针,能够释放,避免忘记释放。

class person
{
public:
	person(int a)
	{
		this->m_A = a;
	}
	void showage()
	{
		cout << "年龄是:" << this->m_A << endl;
	}
private:
	int m_A;
};
//智能指针,意思是用来删除开辟的堆空间的
class smartpoint
{
public:
	smartpoint(person* person)
	{
		this->person = person;
	}
	~smartpoint()
	{
		if (this->person != NULL)
		{
			delete this->person;
			this->person = NULL;
		}
	}
private:
	person* person;
};
void test01()
{
	smartpoint(new person(20));//开辟到堆空间,而类当中能自动释放
}

重点是:

	smartpoint(person* person)
	{
		this->person = person;
	}
	~smartpoint()
	{
		if (this->person != NULL)
		{
			delete this->person;
			this->person = NULL;
		}
	}

将堆空间释放,避免忘记。

->符号重载

class smartpoint
{
public:
	person* operator->()
	{
		return this->person;
	}
private:
	person* person;
};
void test01()
{
    smartpoint sp(new person(20));//开辟到堆空间,而类当中能自动释放
    //重载之后,可以直接用person里面的函数。
	sp->showage();

}

*符号重载

class smartpoint
{
public:
	person& operator*()
	{
		return *this->person;
	}
private:
	person* person;
};
void test01()
{
	smartpoint sp(new person(20));//开辟到堆空间,而类当中能自动释放
	(*sp).showage();
}

5.赋值运算符重载

  就是避免堆空间重复删除,也是关于深拷贝和浅拷贝的问题。

class person2
{
public:
	void operator=(const person2& p)
	{
		if (this->p_name != NULL)
		{
			delete[]this->p_name;
			this->p_name = NULL;
		}
		this->p_name = new char[strlen(p.p_name) + 1];
		strcpy(this->p_name, p.p_name);
	}
	char* p_name;
};

Twelve 类运算符重载

 

 

上一篇:数据分析 大数据之路 六 matplotlib 绘图工具


下一篇:通过3个Hello World应用来了解ASP.NET 5应用是如何运行的(3)