C++操作符重载+、-、*、/、[]、()、<<、>>、=、new、delete、&&、||、++、--、+=、强制转换重载

内容汇总

#include <iostream>
using namespace std;

class A {
	//友元函数,类外函数访问私有变量
	//friend A operator-(const A& c1, const A& c2);
	//friend A& operator+=(A& c1, const A& c2);
	//friend A& operator++(A& c);//++a
	//friend A operator++(A& c, int);//a++
	//重载<<和>>最好在类外
	friend ostream& operator<<(ostream& os, A& c);
	friend istream& operator>>(istream& is, A& c);
private:
	int a;
	int b;
public:
	A(int a = 0, int b = 0) :a(a), b(b) {}
	void print() {
		cout << a << "+" << b << endl;
	}
	//类内重载-
	A operator-(const A& another) {
		A c((this->a) - another.a, (this->b) - another.b);
		return c;
	}
	//类内重载+
	A operator+(const A& another) {
		A c((this->a) + another.a, (this->b) + another.b);
		return c;
	}
	//类内重载+=
	A& operator+=(const A& another) {
		(*this).a += another.a;
		(*this).b += another.b;
		return (*this);
	}
	//类内重载++a
	A& operator++() {
		(*this).a++;
		(*this).b++;
		return (*this);
	}
	//类内重载a++,需要默认参数,此处不需要返回&
	A operator++(int) {
		A tmp = (*this);
		(*this).a++;
		(*this).b++;
		return tmp;
	}
	//类内重载=
	A& operator=(const A& c) {
		if (this == &c)
			return (*this);
		(*this).a = c.a;
		(*this).b = c.b;
		return (*this);
	}
};
类外重载-
//A operator-(const A& c1, const A& c2) {
//	A c(c1.a - c2.a, c1.b - c2.b);
//	return c;
//}
类外重载+
//A operator-(const A& c1, const A& c2) {
//	A c(c1.a + c2.a, c1.b + c2.b);
//	return c;
//}
类外重载+=
//A& operator+=(A& c1,const A& c2) {
//	c1.a += c2.a;
//	c1.b += c2.b;
//	return c1;
//}
类外重载++a
//A& operator++(A& c) {
//	c.a++;
//	c.b++;
//	return c;
//}
类外重载a++
//A operator++(A& c,int) {
//	A tmp = c;
//	c.a++;
//	c.b++;
//	return tmp;
//}
//<<和>>最好类外重载
ostream& operator<<(ostream& os, A& c) {
	os << c.a << '+' << c.b;
	return os;
}
istream& operator>>(istream& is, A& c) {
	is >> c.a >> c.b;
	return is;
}
int main() {
	A c1(1, 1), c2(2, 2), c3;
	cin >> c3;
	cout << c3 << endl;
}

一.来源

假设,现在有类A:

class A {
public:
	A(int a) {
		this->a = a;
	}
private:
	int a;
};

定义:

A a1(1), a2(2);

现在我想直接执行两个类的相加a1+a2,但是C++没有这种方法,所以引出操作符重载。

二.实现

现在实现两个虚数相加:(1+2i)+(3+4i).
先看2种普通实现方法:
方法一:

class Complex {
	friend Complex complexadd(Complex& c1, Complex& c2);//定义友元函数
public:
	Complex(int a,int b) {
		this->a = a;
		this->b = b;
	}
	void printComplex() {
		cout << "(" << this->a << "," << this->b << "i)" << endl;
	}
private:
	int a;//实数
	int b;//虚数
};
//相加
Complex complexadd(Complex& c1, Complex& c2) {
	Complex c3(c1.a + c2.a, c1.b + c2.b);
	return c3;
}
int main() {
	Complex a1(1,2), a2(3,4);
	a1.printComplex();
	a2.printComplex();
	Complex c3 = complexadd(a1, a2);
	c3.printComplex();
}

方法二:

class Complex {
public:
	Complex(int a,int b) {
		this->a = a;
		this->b = b;
	}
	void printComplex() {
		cout << "(" << this->a << "," << this->b << "i)" << endl;
	}
	Complex addcomplex(const Complex& another) {
		Complex a3(this->a + another.a, this->b + another.b);
		return a3;
	}
private:
	int a;//实数
	int b;//虚数
};
int main() {
	Complex a1(1,2), a2(3,4);
	a1.printComplex();
	a2.printComplex();
	Complex a3=a2.addcomplex(a1);
	a3.printComplex();
}

操作符重载方法:
方法一:操作符重载写在全局

class Complex {
	friend Complex operator+(Complex& a1, Complex& a2);//申明友元函数
public:
	Complex(int a,int b) {
		this->a = a;
		this->b = b;
	}
	void printComplex() {
		cout << "(" << this->a << "," << this->b << "i)" << endl;
	}
private:
	int a;//实数
	int b;//虚数
};
//操作符重载写在全局
Complex operator+(Complex& a1, Complex& a2) {
	Complex a3(a1.a + a2.a, a1.b + a2.b);
	return a3;
}
int main() {
	Complex a1(1,2), a2(3,4);
	a1.printComplex();
	a2.printComplex();
	//此处可以直接实现加法!等价于Complex a3 = operator(a1,a2);
	Complex a3 = a1 + a2;
	a3.printComplex();
}

方法二:操作符重载写在局部

class Complex {
public:
	Complex(int a,int b) {
		this->a = a;
		this->b = b;
	}
	void printComplex() {
		cout << "(" << this->a << "," << this->b << "i)" << endl;
	}
	//操作符重载写在局部
	Complex operator+(Complex& another) {
		Complex a3(this->a + another.a, this->b + another.b);
		return a3;
	}
private:
	int a;//实数
	int b;//虚数
};
int main() {
	Complex a1(1,2), a2(3,4);
	a1.printComplex();
	a2.printComplex();
	//此处可以直接实现加法!
	Complex a3 = a1 + a2;
	//等价
	Complex a4 = a1.operator+(a2);
	a3.printComplex();
	a4.printComplex();
}

三.注意事项

1.记住不能重载的,其他都可以重载。

::.
.*?*
sizeoftypeid

2.不能创造重载。例如:a1 666 a2。自己创造一个666运算。
3.重载不能改变运算符的优先级别。

4.重载不能改变运算符的结合性。
5.重载运算符的函数不能有默认参数。
在这里插入图片描述

7.=, ->, [], ()不可以是全局域中的重载(即不能重载为友员函数)

1.重载减号(-)

class A {
	friend A operator-(const A& c1, const A& c2);//申明友元函数
private:
	int a;//实部
	int b;//虚部
public:
	A(int a, int b) {
		this->a = a;
		this->b = b;
	}
	void print() {
		cout << "(" << a << "+" << b << "i)" << endl;
	}
	//操作符重载类内定义
	A operator-(const A& another) {
		A c(this->a - another.a, this->b - another.b);
		return c;
	}
};
//操作符重载外部定义
//A operator-(const A& c1, const A& c2) {
//	A c(c1.a - c2.a, c1.b - c2.b);
//	return c;
//}
int main() {
	A c1(3, 4), c2(1, 2);
	A c = c1 - c2 - c2;
	c.print();
}

2.+=号重载

class A {
	//friend A& operator+=(A& c1, A c2);//友元函数声明
private:
	int a;//实部
	int b;//虚部
public:
	A(int a, int b) {
		this->a = a;
		this->b = b;
	}
	void print() {
		cout << "(" << a << "+" << b << "i)" << endl;
	}
	//"+="操作符重载类内定义
	A &operator+=( A& another) {
		this->a += another.a;
		this->b += another.b;
		return *this;
	}
};
//“+=”操作符重载外部定义
/*A& operator+=(A& c1, A c2) {
	c1.a += c2.a;
	c1.b += c2.b;
	return c1;
}*/
int main() {
	A c1(3, 4), c2(1, 2);
	c1 += c2;
	c1.print();
}

3.++a重载

class A {
	//friend A& operator++(A& c);//友元函数声明
private:
	int a;//实部
	int b;//虚部
public:
	A(int a, int b) {
		this->a = a;
		this->b = b;
	}
	void print() {
		cout << "(" << a << "+" << b << "i)" << endl;
	}
	//"++"操作符重载类内定义
	A & operator++( ) {
		this->a++;
		this->b++;
		return *this;
	}
};
//“++”操作符重载外部定义
/*A& operator++(A& c) {
	c.a++;
	c.b++;
	return c;
}*/
int main() {
	A c1(3, 4), c2(1, 2);
	++c1;
	c1.print();
}

4.a++重载

这里是C++一个坑,用没有意义的占位参数,标识是后++。

class A {
	//friend A& operator++(A& c,int);//友元函数声明
private:
	int a;//实部
	int b;//虚部
public:
	A(int a, int b) {
		this->a = a;
		this->b = b;
	}
	inline void print() {
		cout << "(" << a << "+" << b << "i)" << endl;
	}
	//"++a"操作符重载类内定义
	A& operator++( ) {
		this->a++;
		this->b++;
		return *this;
	}
	//"a++"操作符重载类内定义
	A  operator++( int ) {//此处不能用const A&,因为temp在函数运行完成后被释放,此处不必返回&
		A temp=*this;//用一个临时变量
		this->a++;
		this->b++;
		/*
		++(*this);//或者直接调用++a,代替上面两步,更爽!
		*/
		return temp;
	}
};
#if 0
//“a++”操作符重载外部定义
A operator++(A& c, int) //int为占位参数,用来标识后++,此处返回值不必为&
{
	A temp=c;
	c.a++; c.b++;
	return temp;
}
#endif // 0
int main() {
	A c1(3, 4), c2(1, 2);
	c1++;
	c1.print();
}

5.为什么这里都用&引用

A& operator++(A& c)

如果不用引用,就无法实现连加,目的还是为了防止函数执行完后返回的匿名对象被释放掉,后面就无法访问其值。

为什么a++,不必返回引用呢?因为即使返回引用,得到的值,也只是第一次++后的值。因为后++返回的是temp,不是*this。
前++返回当前对象,离开这个函数后,当前对象依然存在,因此可以返回引用;后++返回是一个局部对象,离开函数就被消亡,因此不能返回引用!
看下面例子也能明白。
在这里插入图片描述

6.<<左移操作符重载

作用:实现直接输出类中变量的值。
在这里插入图片描述
查看cout类型:鼠标放在cout上,右键点击转到定义。
在这里插入图片描述
实现:

class A {
	//friend ostream& operator<<(ostream& os, A& t);//友元函数申明
private:
	int a;
	int b;
public:
	A(int a, int b) {
		this->a = a;
		this->b = b;
	}
	//类内重载
	ostream& operator<<(ostream& os) {
		os << "a=" << this->a << ",b=" << this->b << endl;
		return os;
	}
};
//重载外部定义
/*ostream& operator<<(ostream& os, A& t) {
	os << "a=" << t.a << ",b=" << t.b << endl;
	return os;
}*/
int main(int argc, char** argv)
{
	A t1(1, 2);
	t1 << cout;//类内重载,写法很奇怪
	//cout << t1 << endl;//类外重载
}

注意:为什么ostream& operator<<(ostream& os, A& t),返回是ostream。

	int a = 1;
	int b = 2;
	int c = 3;
	cout << a << b << c << endl;
因为cout<<a,返回值是cout,然后才能继续输出后面cout<<b,cout<<c<<endl;

7.>>右移操作符重载

class A {
	friend istream& operator>>(istream& in, A& t1);//友元函数申明
private:
	int a;
	int b;
public:
	A() {
		this->a = 0;
		this->b = 0;
	}
	~A() {
		cout << "a=" << this->a << ",b=" << b << endl;
	}
};
//重载外部定义
istream& operator>>(istream& is, A& t1) {
	is >> t1.a;
	is >> t1.b;
	return is;
}
int main(int argc, char** argv)
{
	A t1;
	cin >> t1;
}

8.=操作符重载

class Student
{
public:
	Student() {
		this->id = 0;
		this->name = nullptr;
	}
	//拷贝构造
	Student(int id, char* name) {
		this->id = id;
		//对*name一定要申请空间,否则浅拷贝,数据不安全。
		int len = strlen(name);//判断字符数组长度,用strlen,不是size、sizeof
		this->name = new char[len+1];//+1是为了预留一个'\0'
		strcpy_s(this->name,len+1, name);
	}
	//深拷贝构造
	Student(const Student& s) {
		this->id = s.id;
		this->name = new char[strlen(s.name)+1];
		strcpy_s(this->name, strlen(s.name) + 1,s.name);
	}
	~Student() {
		if (this->name != nullptr) {
			delete[] this->name;
			this->name = nullptr;
			this->id = 0;
		}
	}
	void print() {
		cout << "id=" << this->id << ",name=" << this->name << endl;
	}
	//"="操作符重载
	Student& operator=(Student& s) {
		//1.s=s,直接返回本身。
		if (this == &s)
			return *this;
		//2.先将原来空间释放掉
		if (this->name != nullptr) {
			delete[] this->name;
			this->name = nullptr;
			this->id = 0;
		}
		//3.执行深拷贝
		this->id = s.id;
		this->name = new char[strlen(s.name) + 1];
		strcpy_s(this->name, strlen(s.name) + 1, s.name);
		return *this;
	}
private:
	int id;
	char* name;
};
int main() {
	char name1[64] = "abc";
	Student s1(1, name1);
	//在这里等号实际上为拷贝构造,等价于s2(s1);
	Student s2=s1;
	s2.print();
	char name2[64] = "def";
	//“=”操作符重载
	Student s3(2, name2);
	s2 = s3;
	s2.print();
}

9.重载小括号()

class Sqr
{
public:
	Sqr(int a) {
		this->a = a;
	}
	//重载小括号“()”
	int operator()(int b) {
		return b * b;
	}
	int operator()(int b, int c) {
		return b * c;
	}
private:
	int a;
};
int main() {
	Sqr s1(1);
	//s1(2)将对象当成一个普通函数来调用,称这种对象是仿函数或伪函数
	int value1=s1(2);
	cout << value1 << endl;
	int value2 = s1(3, 4);
}

10.new和delete重载

void和void之间没有任何关系,void是一个万能指针。
使用new可以触发类的构造函数,使用delete会触发类的析构函数。

class A
{
public:
	A(int a) {
		cout << "调用了有参构造函数" << endl;
		this->a = a;
	}
	void print() {
		cout << "a=" << a << endl;
	}
	//new操作符重载,void*返回一个万能指针,size_t是申请内存大小
	//重载的new操作符,依然会触发对象的构造函数
	void* operator new(size_t size) {
		cout << "重载了new操作符" << endl;
		return malloc(size);
	}
	void operator delete(void* p) {
		cout << "重载了delete操作符" << endl;
		if (p != nullptr) {
			free(p);
			p = nullptr;
		}
	}
	~A() {
		cout << "触发了析构函数" << endl;
	}
private:
	int a;
};
int main() {
	//等价于ap->operator new(sizeof(A));这里的10会触发构造函数
	A* ap = new A(10);
	ap->print();
	delete ap;
}

结果:
在这里插入图片描述

11.[ ]重载

class A
{
public:
	A() {
		this->a = 0;
	}
	A(int a) {
		cout << "调用了有参构造函数" << endl;
		this->a = a;
	}
	void print() {
		cout << "a=" << a << endl;
	}
	//new操作符重载,void*返回一个万能指针,size_t是申请内存大小
	//重载的new操作符,依然会触发对象的构造函数
	void* operator new[](size_t size) {
		cout << "重载了new[]操作符" << endl;
		return malloc(size);
	}
	void operator delete[](void* p) {
		cout << "重载了delete操作符" << endl;
		if (p != nullptr) {
			free(p);
			p = nullptr;
		}
	}
	~A() {
		cout << "触发了析构函数" << endl;
	}
private:
	int a;
};
int main() {
	//触发无参构造,实际上申请空间大小sizeof(A)*10
	A* ap = new A[10];
	ap->print();
	//触发10次void operator delete[](void* p)
	delete[] ap;
}

结果:
在这里插入图片描述

12.&&和| |重载(不建议重载这两个)

首先看以下代码:

int a = 0;
	if (a && (a = 10)) {//在这里a=10被短路了,没有执行。
	}
	cout << "a=" << a << endl;

结果:
在这里插入图片描述
实现&&重载代码:

class Test {
private:
	int value;
public:
	Test(int value) {
		this->value = value;
	}
	//重载&&
	bool operator&&(Test&  another) {
		cout << "执行了&&操作符重载!" << endl;
		if ( this->value&&another.value)
		{
			return true;
		}
		else {
			return false;
		}
	}
};
int main() {
	Test t1(10), t2(20);
	if (t1 && t2) {//t1.operator&&(t2)
		cout << "t1和t2都不为空" << endl;
	}
	else {
		cout << "t1或t2为空" << endl;
	}
}

结果:
在这里插入图片描述

class Test {
private:
	int value;
public:
	Test(int value) {
		this->value = value;
	}
	/*~Test() {
		cout << "value=" << value << endl;
	}*/
	//重载&&
	void print() {
		cout << "value=" << value << endl;
	}
	bool operator||(Test&  another) {
		cout << "执行了&&操作符重载!" << endl;
		if ( this->value||another.value)
		{
			return true;
		}
		else {
			return false;
		}
	}
	//重载+
	Test& operator+(Test& another) {
		this->value += another.value;
		return *this;
	}
};
int main() {
	Test t1(0), t2(20);
	if (t1 ||  t2) {
		cout << "t1或t2不为0" << endl;
	}
	else {
		cout << "t1和t2都为0!" << endl;
	}
}

结果:
在这里插入图片描述

13.强制类型转换

class boolean {
	//输出,false输出false,true输出true
	friend ostream& operator<<(ostream& os, const boolean& b);
	friend istream& operator>>(istream& is, boolean& b);
private:
	bool data;
public:
	boolean(const bool d = false) :data(d) {}
	~boolean() {}
	//强制类型转换:实现(int)boolean或int(boolean)输出1或0
	operator int() const { return (data ? 1 : 0); }
};
#include "boolean.h"
ostream& operator<<(ostream& os, const boolean& b) {
	os << (b.data == true ? "true" : "false");
	return os;
}
istream& operator>>(istream& is, boolean& b) {
	string tmp;
	is >> tmp;
	b.data = (tmp == "true" ? true : false);
	return is;
}
int main() {
	boolean b(true);
	cout << (int)b << endl;//此处使用强制类型转换
	cout << int(b) << endl;//同上
}
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值