C++学习——运算符重载operator

加号运算符重载

自定义数据类型实现运算

在成员函数 或者 全局函数 中重写一个+运算符的函数

函数名 operator+()

运算符重载也可以提供多个版本:Person p4 = p3+10;

//加号运算符重载
//自定义数据类型也可以实现一个加号运算
class Person
{
public:
	Person()
	{

	}

	Person(int a, int b) :m_A(a), m_B(b)
	{}

	//+运算符重载,成员函数
	Person operator+(Person &p)   //二元函数
	{
		Person tmp;
		tmp.m_A = this->m_A + p.m_A;
		tmp.m_B = this->m_B + p.m_B;
		return tmp;
	}
	int m_A;
	int m_B;
};

//+运算符重载, 全局函数
Person operator+(Person &p1, Person &p2)  //二元函数
{
	Person tmp;
	tmp.m_A = p1.m_A + p2.m_A;
	tmp.m_B = p1.m_B + p2.m_B;
	return tmp;
}

void test02()
{
	Person p1(10, 10);
	Person p2(10, 10);

	//p3 = p1 + p2
	Person p3 = p1 + p2;  //直接这样写会出现 没有与这些操作数匹配的运算符
	/*------------解决这个问题就是在类里面加一个重载Person operator+(Person &p)------------*/
}

左移运算符重载

不要随意使用符号重载,内置数据类型(int, float等)的运算符是不可以重载的

左移运算符重载不能写道成员函数中,要写到全局函数中

函数名 operator<<()

//左移运算符重载
class Person1
{
public:
	friend ostream &operator<<(ostream &cout, Person1 &p);

	Person1(int a, int b)
	{
		this->m_A = a;
		this->m_B = b;
	}

private:
	int m_A;
	int m_B;
};

ostream &operator<<(ostream &cout, Person1 &p)  //把它作为友元函数,就可以调用私有属性
{
	cout << "m_A = " << p.m_A << ", m_B = " << p.m_B;
	return cout;
}

void test03()
{
	Person1 p1(10, 10);
	cout << p1 << endl;   //直接写会出现没有与操作数匹配的运算符<<
	/*--------------解决方法是实现左移运算符重载,但是重载左移不能写到成员函数中--------------*/
}

前置后置递增递减运算符重载

优先使用前置,前置比后置效率更高,因为后置需要创建一个变量

class MyInteger
{
public:

	MyInteger()
	{
		m_Num = 0;
	}

	//前置++重载
	MyInteger& operator++()
	{
		this->m_Num++;
		return *this;
	}

	//后置++重载, 用占位参数区分前置还是后置
	MyInteger operator++(int)
	{
		MyInteger tmp = *this; //先保存下临时的值
		m_Num++;
		return tmp;
	}

	int m_Num;
};

ostream &operator<<(ostream &cout, MyInteger &myInt)
{
	cout << myInt.m_Num;
	return cout;
}

void test04()
{
	MyInteger num;
	cout << ++num << endl;
	cout << num++ << endl;
	cout << num << endl;
}

指针运算符重载(智能指针)

用来维护一个自定义类型的对象指针,让对象进行自动释放

为了让智能指针和一般的指针一样用->和*,因此需要重载->和*。

//指针运算符重载(智能指针)
//用来托管自定义类型的对象,让对象进行自动释放
class Person2
{
public:
	Person2(int age)
	{
		this->Age = age;
	}
	void showAge()
	{
		cout << "年龄为:" << this->Age << endl;
	}
	~Person2()
	{
		cout << "调用析构函数" << endl;
	}

	int Age;
};

class smartPointer
{
public:
	smartPointer(Person2 *person)
	{
		this->person = person;
	}

	//重载智能指针,使得sp->showAge()
	Person2* operator->()
	{
		return this->person;
	}

	Person2& operator*()
	{
		return *this->person;
	}

	~smartPointer()
	{
		cout << "智能指针析构" << endl;
		if (this->person != NULL)
		{
			delete this->person;
			this->person = NULL;
		}
	}
private:
	Person2 *person;
};

void test05()
{
	//Person2 p1(10);//自动会析构,因为开辟到了栈上
	//Person2 *p2 = new Person2(10);  //不会自动析构,因为开辟在堆上,因此要用delete

	//delete p2;

	smartPointer sp(new Person2(10));
	sp->showAge();   //本来应该是sp->sp->showAge();这是编译器对其进行了优化
	(*sp).showAge();
}

赋值运算符重载

系统默认给类提供了一个简单的赋值运算符重载,简单值拷贝

导致如果类中有指向堆区的指针(char *name),就可能会出现深浅拷贝的问题,所以要重载=运算符

如果想链式编程,就return *this

//赋值运算符重载
//一个类默认创建:默认构造、析构、拷贝构造、operator=赋值运算符(进行简单的值传递)
class Person3
{
public:
	Person3(int a)
	{
		this->m_A = a;
	}

	int m_A;
};

class Person4
{
public:
	Person4(const char *name)
	{
		this->pName = new char[strlen(name) + 1];
		strcpy(this->pName, name);
	}

	Person4& operator=(const Person4& p)
	{
		//先判断 如果原来已经堆区有内容,先释放
		if (this->pName != NULL)
		{
			delete[] this->pName;
			this->pName = NULL;
		}

		this->pName = new char[strlen(p.pName) + 1];
		strcpy(this->pName, p.pName);
		
		return *this;
	}

	~Person4()
	{
		if (this->pName != NULL)
		{
			delete[] this->pName;
			this->pName = NULL;
		}
	}

	char *pName;
};

void test06()
{
	//Person3类中只有简单的默认赋值运算符
	Person3 p(10);
	Person3 p1(0);

	p1 = p;
	cout << "p1.m_A = " << p1.m_A << endl;  //10


	Person4 p2("张三");
	Person4 p3("李四");
	Person4 p5("老王");
	//p3 = p2;   //直接这样写的话就会出现浅拷贝的问题,因为指向同一空间,因此析构完p2后,析构p3会出现中断
	cout << "p2.name = " << p2.pName << endl;
	/*  出现上面错误的关键问题就是=赋值运算符太简单了,解决上面的问题就在类里面写一个=重载运算符   */
	p5 = p3 = p2;
	cout << "p5.name = " << p5.pName << endl;
}

[ ]运算符重载

int& MyArray::operator[] (int index)

函数调用运算符重载

class MyPrint
{
public:
	void operator()()
	{
		cout << "Hello world!" << endl;
	}
	void operator()(string text)
	{
		cout << text << endl;
	}
};
void test08()
{
	MyPrint myPrint;
	myPrint();        //仿函数,不是一个函数,是一个类下面的对象,只是里面的操作跟函数差不多
	myPrint("你好");
}

不能重载 && 和 || 运算符

因为会失去它们原有的短路特性

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值