18、运算符重载

目的:对运算符再定义,以适应不同的数据类型

一、加号(+)运算符重载

1、自己写函数,实现两个对象相加

Person Person::addPerson(Person& p)
{
    Person temp;
    temp.m_A = this->m_A + p.m_A;
    temp.m_B = this->m_B + p.m_B;
    return temp;                     //调用拷贝构造函数
}

Person p3=p2.addPerson(p1);   //不能写成 p3 = p1 + p2;

2、通过成员函数重载

Person 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;                     //调用拷贝构造函数
}

Person p4 = p1.operator+(p2);

Perosn p4 = p1+ p2;

3、通过全局函数重载

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;                     //调用拷贝构造函数
}

Person p5 = operator+(p1,p2);

Person p5 = p1+ p2;

4、运算符重载也可以发生函数重载

Person operator+(Person& p, int num)
{

    Person temp;
    temp.m_A = p.m_A + num;
    temp.m_B = p.m_B + num;
    return temp;                     //调用拷贝构造函数
}

Person p6 = operatot+(p1,10)

Person p6 = p1 + 10;

————————————

通过对加号重载,可以使得:Person p3 = p1.operator+(p2);

简化:Person p3 = p1 + p2;

内置数据类型,不可以重载

#include<iostream>
using namespace std;

class Person
{
public:
	Person operator+(Person& p);
	Person addPerson(Person& p);
public:
	int m_A;
	int m_B;
};

//自己写函数,实现两个对象相加
Person Person::addPerson(Person& p)
{
	Person temp;
	temp.m_A = this->m_A + p.m_A;
	temp.m_B = this->m_B + p.m_B;
	return temp;					 //调用拷贝构造函数
}

Person 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;					 //调用拷贝构造函数
}

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;					 //调用拷贝构造函数
}

Person operator+(Person& p, int num)
{
	Person temp;
	temp.m_A = p.m_A + num;
	temp.m_B = p.m_B + num;
	return temp;					 //调用拷贝构造函数
}

void test01()
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 10;

	Person p2;
	p2.m_A = 10;
	p2.m_B = 10;

	//1.自己定义
	Person p3=p2.addPerson(p1);
	//Person p3 = p1 + p2;
	cout << "addPerson :" << p3.m_A << " " << p3.m_B << endl;

	//2.成员函数重载
	Person p4 = p1.operator+(p2);
	//Person p4 = p1 + p2;
	cout << "成员函数 operator+ :" << p4.m_A << " " << p4.m_B << endl;

	//3.全局函数重载
	Person p5 = operator+(p1,p2);
	//Person p4 = p1 + p2;
	cout << "全局函数 operator+ :" << p5.m_A << " " << p5.m_B << endl;

	//运算符重载也可以发生函数重载
	Person p6 = p1 + 10;
	cout << "全局函数 operator+ :" << p6.m_A << " " << p6.m_B << endl;

}

int main()
{
	test01();

	system("pause");
	return 0;
}

二、左移(<<) 运算符重载

目的:输出自定义数据类型

//p.operator(cout)  p<<cout
1、不会利用成员函数重载左移运算符
//void opretor<< (Person& p);  //p.operator<<(p)  ×

———————————————

2、全局函数,重载<<

//本质:operator<<(cout,p)    简化:cout<<p

//cout 只有一个,只能用引用的方式,    //out 是cout取的别名

ostream& operator<<(ostream &out, Person &p)    //以引用的方式返回
             
    out << "m_A=" << p.m_A << endl;
    out << "m_B=" << p.m_B << endl;
    return out;
}

#include<iostream>
using namespace std;

class Person
{
public:
	//p.operator(cout)  p<<cout
	//不会利用成员函数重载左移运算符
	//void opretor<< (Person& p);  //p.operator<<(p)  ×
public:
	int m_A;
	int m_B;
};

					//out 是cout取的别名
ostream& operator<<(ostream &out, Person &p)  
{			   //本质:operator<<(cout,p)    简化:cout<<p
			   //cout 只有一个,只能用引用的方式
	out << "m_A=" << p.m_A << endl;
	out << "m_B=" << p.m_B << endl;
	return out;
}

void test01()
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 20;

	//void operator<<(ostream &out, Person &p)
	//cout << p1;

	//ostream& operator<<(ostream &out, Person &p)
	cout << p1 << "hello" << endl;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

三、递增(++)重载

1、重载前置++运算符
    MyInteger& operator++()   //返回的是引用,返回本身,而不是新拷贝的对象
    {    //先++
        ++m_Num;
        //再返回自身,调用,<<重载运算符,输出
        return *this;
    }

2、重载后置++运算符
前置递增返回引用,后置递增返回值

置递增返回值:后置递增返回的是栈上开辟的空间
MyInteger operator++(int)  //int 占位参数,区别前置后置++函数
{
     //m_Num++;   ×
     MyInteger temp = *this;
     m_Num++;

     return temp;
}

————————————

(1) MyInteger& operator++()   //返回的是引用,返回本身,而不是新拷贝的对象
{    
     ++m_Num;
     return *this;
 }

cout << ++(++myint) << endl;     2
cout << myint << endl;                2

(2) MyInteger operator++()   //返回的是新拷贝的对象

cout << ++(++myint) << endl;       2
cout << myint << endl;                  1  //这里为1

#include<iostream>
using namespace std;

class MyInteger
{
public:
	MyInteger()
	{
		m_Num = 0;
	}
	friend ostream& operator<<(ostream& out, MyInteger myint);
public:
	//重载前置++运算符
	MyInteger& operator++()   //返回的是引用,返回本身,而不是新拷贝的对象
	{	//先++
		++m_Num;
		//再返回自身,调用,<<重载运算符,输出
		return *this;
	}

	//重载前置++运算符
	//后置递增返回值,前置递增返回引用
	MyInteger& operator++(int)  //int 占位参数,区别前置后置++函数
	{
		//m_Num++;
		MyInteger temp = *this;
		m_Num++;
		return temp;
	}

private:
	int m_Num;
};

ostream& operator<<(ostream& out, MyInteger myint)
{
	out << myint.m_Num;
	return out;
}

void test01()
{
	MyInteger myint;
	cout << ++(++myint) << endl;
	cout << myint << endl;
}

void test02()
{
	MyInteger myint;
	cout << myint++ << endl;
	cout << myint << endl;
}

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

	system("pause");
	return 0;
}

四、赋值(=)重载

c++编译器至少给一个类添加4个函数

(1)、默认构造函数(无参,空函数体)

(2)、默认析构函数(无参,空函数体)

(3)、拷贝构造函数(拷贝成员变量值)

(4)、赋值运算符重载,operator=,对属性值进行拷贝

若类中有属性指向堆区,也存在深、浅拷贝问题

——————————————

Person& operator=(Person& p)
{
    //深拷贝之前,调用构造函数,堆区已经有内容了
    //(1)、先释放原有堆区内容,再进行深拷贝(重新在堆区申请空间)
    if (m_Age != NULL)
    {
            delete m_Age;
            m_Age = NULL;
    }

      //(2)、堆区重新创建
    this->m_Age = new int(*p.m_Age);

   //(3)、返回对象本身
    return *this;
}

——————————————

    Person p1(19);
    Person p2(20);
    Person p3(21);

    //p2 = p1;  //堆区内存重复释放,堆区崩溃
    //          //利用深拷贝,解决浅拷贝

    p3 = p2 = p1;  //p2=p1,应该返回本身p2

——————————————

(1)、如果成员变量存在在堆区创建的情况,若再次使用系统提供的浅拷贝,会存在堆区内存重复释放问题,程序崩溃。

(2)、此时,需要我们自定义重载=函数,用深拷贝解决浅拷贝。

(3)、深拷贝operator=() 中,先判断原有堆区是否还有内容,有就先释放,然后再申请堆区空间。

(4)、如果还想p3=p2=p1.这种连等,则必须使得operator=() 返回类型为对象本身 Person&。

#include<iostream>
using namespace std;

class Person
{
public:
	Person(int age)
	{
		m_Age = new int(age);
	}
	~Person()
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
	}
	Person& operator=(Person& p)
	{
		//深拷贝之前,调用构造函数,堆区已经有内容了
		//先释放原有堆区内容,再进行深拷贝(重新在堆区申请空间)
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
		//堆区重新创建
		this->m_Age = new int(*p.m_Age);

		//返回对象本身
		return *this;
	}
public:
	int* m_Age;  //类中成员变量,指针,保存堆区开辟空间的地址
};

void test01()
{
	Person p1(19);
	Person p2(20);
	Person p3(21);

	//p2 = p1;  //堆区内存重复释放,堆区崩溃
	//		  //利用深拷贝,解决浅拷贝

	p3 = p2 = p1;  //p2=p1,应该返回本身p2

	cout << "p1的年龄:" << *p1.m_Age << endl;
	cout << "p2的年龄:" << *p2.m_Age << endl;
	cout << "p3的年龄:" << *p3.m_Age << endl;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

五、关系运算符重载

==    !=

重载目的:比较自定义数据类型时,我们需要重载关系运算符

    bool operator==(Person& p)
    {
        if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

#include<iostream>
using namespace std;
#include<string>

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

void test01()
{
	Person p1("张三", 18);
	Person p2("李四", 18);

	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;
}

六、函数调用运算符重载

函数调用运算符()

()重载后的使用方式非常像函数调用,因此称为仿函数

仿函数:在类中,重载的小括号

(01)、函数调用

void MyPrint02(string test)
{
    cout << test << endl;
}
MyPrint02("Hello word 2");    //函数调用

(1)、打印类

class MyPrint
{
public:
    void operator()(string test)
    {
        cout << test << endl;
    }
};

MyPrint myPrint;
myPrint("hello word");  
//使用起来,非常像函数调用,所以叫仿函数

//函数调用:MyPrint02("Hello word 2");    //函数名()

//仿函数myPrint("hello word");                //对象名()

匿名函数对象:MyPrint( )("匿名函数对象");

(2)、加法类

class MyAdd
{
public:
    int operator()(int num1, int num2)
    {
        return num1 + num2;
    }
};
    MyAdd myAdd;
    int ret = myAdd(10, 20);

    cout << ret << endl;

    //匿名函数对象
    cout << MyAdd()(100, 200) << endl;

}

#include<iostream>
using namespace std;
#include<string>

//class MyPrint
//{
//public:
//	MyPrint(string test)
//	{
//		m_test = test;
//	}
//public:
//	void operator()()
//	{
//		cout << m_test << endl;
//	}
//public:
//	string m_test;
//};

class MyPrint
{
public:
	void operator()(string test)
	{
		cout << test << endl;
	}
};

void MyPrint02(string test)
{
	cout << test << endl;
}

void test01()
{
	//1.
	//MyPrint myPrint("hello");
	//myPrint.operator()();

	//2.仿函数
	MyPrint myPrint;
	myPrint("hello word");   //使用起来,非常像函数调用,所以叫仿函数

	MyPrint()("匿名函数对象");

	//函数调用
	MyPrint02("Hello word 2");

}


//仿函数非常灵活
class MyAdd
{
public:
	int operator()(int num1, int num2)
	{
		return num1 + num2;
	}
};

void test02()
{
	MyAdd myAdd;
	int ret = myAdd(10, 20);

	cout << ret << endl;

	//匿名函数对象
	cout << MyAdd()(100, 200) << endl;

}

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

	system("pause");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值