第四课 类和对象-运算符重载

4.5 C++运算符重载
4.5.1 加号运算符重载
作用:实现两个自定义数据类型相加的运算

class Number
{
public:
	// 通过成员函数重载 + 运算符
	Number operator+(Number& number)
	{
		Number temp;
		temp.m_A = this->m_A + number.m_A;
		temp.m_B = this->m_B + number.m_B;

		return temp;
	}
	int m_A;
	int m_B;
};
//// 通过全局函数 重载加号运算符
//Number operator+(Number& n1, Number& n2)
//{
//	Number temp;
//	temp.m_A = n1.m_A + n2.m_A;
//	temp.m_B = n1.m_B + n2.m_B;
//
//	return temp;
//}

void test01()
{
	Number n1;
		n1.m_A = 10;
		n1.m_B = 25;

		Number n2;
		n2.m_A = 10;
		n2.m_B = 25;

		Number n3 = n1 + n2;

		cout << n3.m_A << " " << n3.m_B << endl;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

4.5.2 左移运算符重载
作用:可以输出自定义数据类型

class Person
{
public:
	// 利用成员函数重载左移运算符 p.operator<<(p) 简化 p << cout 
	// 通常不会利用成员函数重载左移运算符,因为无实现 cout 在左侧
	/*void operator<<(ostream &cout)
	{
		cout << "姓名:" << this->m_Name << " 年龄:" << this->m_Age << endl;
	}*/

	string m_Name;
	int m_Age;
};

ostream& operator<<(ostream& cout,Person &p)
{
	cout << "姓名:" << p.m_Name << " 年龄:" << p.m_Age << endl;

	return cout;
}

void test01()
{
	Person p1;
	p1.m_Name = "张三";
	p1.m_Age = 18;
	//p1 << cout;
	// 链式编程
	cout << p1 << endl;

}

int main()
{
	test01();
	system("pause");
	return 0;
}

4.5.3 递增运算符重载
作用:通过重载递增运算符,实现自己的整形数据

class Person
{
public:
	// 重载前置++运算符 返回引用为了对一个数据进行递增操作
	Person& operator++()
	{
		m_Age++;
		return *this;
	}
	// 重载后置++运算符 int代表占位参数,可用于区分前置和后置递增
	Person operator++(int)
	{
		Person temp = *this; // 局部对象的引用,当前函数结束后会释放;故返回值
		m_Age++;
		return temp;
	}
	int m_Age;
};

ostream& operator<<(ostream& cout, Person p)
{
	cout << "年龄:" << p.m_Age << endl;
	return cout;
}

void test01()
{
	Person p;
	p.m_Age = 23;

	cout << ++(++p);
	cout << p++;
	cout << p;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

注意:前置递增返回引用,后置递增返回值
4.5.4 赋值运算符重载
C++编译器至少给一个类添加四个函数:
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对属性进行值拷贝
4.赋值运算符operator=对属性进行值拷贝

如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

class Person
{
public:
	Person& operator=(Person& p)
	{
		// 编译器提供的是浅拷贝
		// m_Name = p.m_Name

		// 应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
		if (m_Name != NULL)
		{
			delete m_Name;
			m_Name = NULL;
		}
		// 深拷贝
		m_Name = new string(*p.m_Name);
		// 返回对象本身
		return *this;
	}
	Person(string name)
		{
			m_Name = new string(name);
		}
	~Person()
	{
		if (m_Name != NULL)
				{
					delete m_Name;
					m_Name = NULL;
				}
	}

	string *m_Name;
};

void test01()
{
	Person p1("张三");
	Person p2("李四");
	Person p3("王五");

	p1 = p2 = p3;
	cout << *p1.m_Name << endl;

}

int main()
{
	test01();

	system("pause");
	return 0;
}

4.5.5 关系运算符重载
作用:重载关系运算符,可以让两个自定义类型对象进行对比操作

class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}
	bool operator==(Person &p)
	{
		if (m_Name == p.m_Name && m_Age == p.m_Age)
		{
			return true;
		}
		return false;
	}
	bool operator!=(Person& p)
	{
		if (m_Name != p.m_Name || m_Age != p.m_Age)
		{
			return true;
		}
		return false;
	}
	string m_Name;
	int m_Age;
};

void test01()
{
	Person p1("dz", 25);
	Person p2("dz", 25);

	if (p1 == p2)
	{
		cout << "p1与p2是相等的!" << endl;
	}
	else
	{
		cout << "p1与p2是不相等的!" << endl;
	}
	if (p1 != p2)
	{
		cout << "p1与p2是不相等的!" << endl;
	}
	else
	{
		cout << "p1与p2是相等的!" << endl;
	}
}

int main()
{
	test01();

	system("pause");
	return 0;
}

4.5.6 函数调用运算符重载

  • 函数调用运算符()也可以重载
  • 由于重载后使用的方法非常像函数的调用,因此称为仿函数
  • 仿函数没有固定写法,非常灵活
class MyPrint
{
public:
	void operator()(string text)
	{
		cout << text << endl;
	}
};
void MyPrint01(string text)
{
	cout << text << endl;
}
void test01()
{
	MyPrint myPrint;

	myPrint("Hellow World"); // 由于使用起来非常类似于函数调用,因此称为仿函数
	MyPrint01("Hellow World!");
}
// 仿函数非常灵活,没有固定的写法
// 加法类
class MyAdd
{
public:
	int operator()(int num1,int num2)
	{
		return num1 + num2;
	}
};
void test02()
{
	MyAdd myAdd;
	int sum = myAdd(25, 25);
	cout << "sum = " << sum << endl;

	// 匿名函数对象
	cout << MyAdd()(125, 125) << endl;
}

int main()
{
	//test01();
	test02();

	system("pause");
	return 0;
}
posted @ 2025-04-15 21:52  起名字太难0123  阅读(30)  评论(0)    收藏  举报