c++ 运算符重载

1、简介

        对于默认类型如int、float等,都具有 + - * / << ++ -- 等运算方法可以使用,而对于用户自定义的类或结构体没有这些运算方法,需要用户自己通过运算符重载的方式生成。

2、加法

        默认使用 operator+ 为函数名,可以在调用时直接使用 a + b的形式

2.1类中的加法运算符重载 + - * / 

        如下例中,operator+成员函数

class Garage {
public:
	float box_num;
	float sum_weight;
	Garage(float num, float weight) {
		this->box_num = num;
		this->sum_weight = weight;
	}
	Garage operator+(Garage& g2) {
		Garage temp(0,0);
		temp.box_num = this->box_num + g2.box_num;
		temp.sum_weight = this->sum_weight + g2.sum_weight;
		return temp;
	}
	void print() {
		cout << "box_num:" << box_num << ",";
		cout << "sum_weight:" << sum_weight << endl;;
	}
};

2.2全局函数的加法运算符重载

Garage operator+(Garage& g1, Garage& g2) {
	Garage temp(0, 0);
	temp.box_num = g1.box_num + g2.box_num;
	temp.sum_weight = g1.sum_weight + g2.sum_weight;
	return temp;
}

2.3 运算符重载函数的重载

Garage operator+(Garage& g1, float num) {
	Garage temp(0, 0);
	temp.box_num = g1.box_num + num;
	temp.sum_weight = g1.sum_weight + num;
	return temp;
}

Garage operator+(Garage& g1, Garage& g2) {
	Garage temp(0, 0);
	temp.box_num = g1.box_num + g2.box_num;
	temp.sum_weight = g1.sum_weight + g2.sum_weight;
	return temp;
}

3、左移运算符重载 <<

3.1 注意点

        a、cout 类型为 ostream类型,只能有一个,因此需要在运算符重载时定义为引用形式&

        b、在运算符重载时需要返回 ostream的引用类型,防止后续还需要输出别的如endl等。

        c、左移运算符重载要使用简便输出,就只能定义为全局函数,且需要在类中定义为友元

3.2 示例

class Garage {
	friend ostream& operator<<(ostream& out, Garage& g1);
public:
	Garage(float num, float weight) {
		this->box_num = num;
		this->sum_weight = weight;
	}
private:
	float box_num;
	float sum_weight;
};

ostream& operator<<(ostream& out, Garage& g1) {
	cout << "box_num:" << g1.box_num << " ,sum_weight :" << g1.sum_weight << endl;
	return out;
}

int main() {

	Garage g1(2,10);

	cout << g1 << endl;

	system("pause");
	return 0;
}

4、++运算符重载

4.1 注意点

        a、前置++,需要采取函数引用形式,来返回已经自加过的值。

        b、后置++,为了防止函数重载,需要加入一个int作为占位,且不用函数引用,使得函数在自加前先返回,再自加。

4.2 示例

        如下示例同样使用了3节中的左移运算符重载:

class Man {
	friend ostream& operator<<(ostream& out, Man m);
public:
	Man(int age) {
		this->age = age;
	}
	//前置++,需要采取函数引用形式,来返回已经自加过的值
	Man& operator++() {
		this->age++;
		return *this;
	}
	//后置++,为了防止函数重载,需要加入一个int作为占位,且不用函数引用,使得函数在自加前先返回,再自加
	Man operator++(int) {
		Man temp(this->age);
		temp.age = this->age++;//先返回,再自加
		return temp;
	}
private:
	int age;
};

ostream& operator<<(ostream& out, Man m) {
	cout << "age:" << m.age << endl;
	return out;
}

int main() {
	Man m1(10);
	cout << ++m1 << endl;
	cout << m1++ << endl;
	cout << m1 << endl;
	system("pause");
	return 0;
}

输出:

5、赋值运算符重载 = 

5.1 拷贝概念

        a、浅拷贝,只是简单更改了指向

        b、深拷贝,先判断当前对象是否有堆区内存,有则先释放内存,再进行空间开辟,存放数据

5.2 注意

        在赋值运算符重载中使用浅拷贝,会在添加了释放内存的析构函数中报错,应该使用深拷贝。

        原因:因为浅拷贝只是简单的将对象内存指针都指向了 存储数据的那个堆区部分 ,并没有在堆区开辟新的内存,导致程序在将要结束前,析构函数对同一个 内存区域进行了多次的内存释放

5.3 示例

class Man {
public:
	Man(int age) {
		this->m_aGe =new int(age);
	}
	~Man() {//如果有指向,则将堆区内存释放
		if (*m_aGe != NULL) {
			delete this->m_aGe;
			m_aGe = NULL;
			
		}
	}
	Man& operator=(Man& m) {
		//浅拷贝,只是简单更改了指向
		//this->m_aGe = m.m_aGe;

		//深拷贝,先判断当前对象是否有堆区,有则先释放,再进行拷贝
		if (this->m_aGe != NULL) {
			m_aGe = NULL;
			delete this->m_aGe;
		}
		this->m_aGe = new int(*m.m_aGe);
		return *this;
	}
	void print() {
		cout << "m_aGe: "<< *(this->m_aGe)<<", 地址 :" << this->m_aGe << endl;
	}
private:
	int * m_aGe;
};

int main() {

	Man m1(10);
	Man m2(20);
	Man m3(30);

	m3 = m2 = m1;

	m1.print();
	m2.print();
	m3.print();

	system("pause");
	return 0;
}

6 、关系运算符重载  < > == != 

6.1 示例

class Man {
public:
	Man(int age) {
		this->m_aGe =new int(age);
	}

	bool operator==(Man& m) {
		if (*m.m_aGe == *this->m_aGe) {
			return true;
		}
		else
			return false;
	}
	bool operator!=(Man& m) {
		if (*m.m_aGe == *this->m_aGe) {
			return false;
		}
		else
			return true;
	}
private:
	int * m_aGe;
};

int main() {

	Man m1(10);

	Man m2(120);

	if (m1 == m2) {
		cout << "m1 = m2" << endl;
	}
	else
		cout << "m1 != m2" << endl;

	if (m1 != m2) {
		cout << "m1 != m2" << endl;
	}
	else
		cout << "m1 = m2" << endl;
	system("pause");
	return 0;
}

7、函数调用运算符重载 ()

        由于函数调用运算符重载 () 与函数的调用非常相似,因此这种方法也被称为仿函数

        示例:

class Man {
public:
	void operator()(string str){
		cout << "you said : " << str << endl;
	}
	int operator()(int a, int b) {
		cout << " you used the add methoed ,result is :" << a + b << endl;
		return a + b;
	}
};

int main() {

	Man m1;

	m1("this man's age are 10");

	//匿名对象调用,当前行运行完了就释放
	Man()("abcdefg");

	int add_r = m1(2, 3);
	system("pause");
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值