【c++】重载运算符|赋值运算符

本文介绍了C++中的运算符重载,它允许为不同类型的对象赋予相同运算符的不同行为。特别是,重载赋值运算符'='时,类型可能不匹配,如将int赋值给complex对象或字符串对象。赋值运算符必须作为成员函数重载,并且需要注意浅复制和深复制的区别,以防止内存管理问题。推荐在重载'='时返回对象的引用,以保持运算符的连续赋值特性。

运算符重载

• 对已有的运算符赋予多重的含义
• 使同一运算符作用于不同类型的数据时 -> 不同类型的行为
• 运算符重载的实质是函数重载
运算符重载为普通函数
重载为普通函数时, 参数个数为运算符目数

class Complex {
	public:
	Complex( double r = 0.0, double i= 0.0 ){
 		real = r;
 		imaginary = i;
	}
	double real; // real part
	double imaginary; // imaginary part
};
Complex operator+ (const Complex & a, const Complex & b)
{
 	return Complex( a.real+b.real, a.imaginary+b.imaginary);
}	 // “类名(参数表)” 就代表一个对象
Complex a(1,2), b(2,3), c;
c = a + b;

运算符重载为成员函数
重载为成员函数时, 参数个数为运算符目数减一

class Complex {
	public:
	Complex( double r= 0.0, double m = 0.0 ):
 		real(r), imaginary(m) { } // constructor
	Complex operator+ ( const Complex & ); // addition
	Complex operator- ( const Complex & ); // subtraction
private:
	double real; // real part
	double imaginary; // imaginary part
};
// Overloaded addition operator
Complex Complex::operator+(const Complex & operand2) {
	return Complex( real + operand2.real, imaginary + operand2.imaginary );
}
// Overloaded subtraction operator
Complex Complex::operator- (const Complex & operand2){
	return Complex( real - operand2.real, imaginary - operand2.imaginary );
}
int main(){
 Complex x, y(4.3, 8.2), z(3.3, 1.1);
 x = y + z;
 x = y - z;
 return 0;
} 

重载赋值运算符

重载运算符两边的类型可以不匹配

  • 把一个int类型变量赋值给一个complex对象
  • 把一个char*类型的字符串赋值给一个字符串对象
    需要重载赋值运算符‘=’
    赋值运算符‘=’只能重载为成员函数,不能重载为普通函数
class String {
	private:
		char * str;
	public:
		String () : str(NULL) { } //构造函数, 初始化str为NULL
		const char * c_str() { return str; }
		char * operator = (const char * s);
		~String();
}; 
//重载 ‘=’  obj = “hello”能够成立
char * String::operator = (const char * s){
	if(str) delete [] str;
	if(s) { //s不为NULL才会执行拷贝
		str = new char[strlen(s)+1];
		strcpy(str, s);
	}
	else
		str = NULL;
	return str;
}
String::~String( ) {
	if(str) delete [] str;
};
int main(){
	String s;
	s = “Good Luck,;
	cout << s.c_str() << endl;
	// String s2 = “hello!”; //这条语句要是不注释掉就会出错
	//调用的是构造函数,但是没有参数为char*的构造函数
	s = "Shenzhou 8!";
	cout << s.c_str() << endl;
	return 0;
}

浅复制/浅拷贝
• 执行逐个字节的复制工作
注意要避免使用浅拷贝,因为浅拷贝实际上是指向了同一块内存空间,可能会面临重复释放内存空间的问题
深复制/深拷贝
• 将一个对象中指针变量指向的内容, 复制到另一个对象中指针成员对象指向的地方

MyString s;
s = “Hello”;
s = s;
//这样是不可以的,可能已经把这块地方的内容删掉了,但是又要用这个地方的内容去赋值给另一个地方
//正确写法
String & String::operator = (const String & s){
	if(str == s.str) return * this;
	if(str) delete [] str;
	if(s.str) { //s.str不为NULL才会执行拷贝
		str = new char[strlen(s.str)+1];
		strcpy( str,s.str);
	}
	else
		str = NULL;
	return * this;
}

对 operator = 返回值类型的讨论
void?不好, a = b = c;//等价于a.operator=(b.operator=c);
String?可以但是不好,尽量用String &,运算符重载时, 好的风格是尽量保留运算符原本的特性,如果(a = b) = c;//会修改a的值
(a.operator=(b)).operator=©;//只有是a的引用才能作为下一个的对象

为 String类编写 复制构造函数时,会面临和 ‘=’ 同样的问题, 用同样的方法处理

<think>嗯,用户让我介绍一下C++运算符重载,对吧?首先我得回忆一下运算符重载的基本概念。运算符重载是允许程序员为自定义类型(比如类或结构体)定义运算符的特殊行为。比如,我们可以让两个对象相加,而不需要每次都调用一个特定的方法。 接下来,我需要考虑用户可能的背景。可能他们有一定的C++基础,知道类和对象的概念,但还不清楚如何自定义运算符的行为。所以应该从基础开始,逐步深入。 首先,运算符重载的作用是什么?主要是让代码更直观,比如复数相加,直接用+号比用add方法更自然。这点很重要,要举例子说明。 然后,重载的方式有两种:成员函数和非成员函数(通常是友元函数)。什么时候用哪种?比如,如果运算符需要访问类的私有成员,可能需要作为友元函数。比如,<<运算符重载用于输出,通常作为友元函数。这部分需要详细说明,最好有例子。 接下来,注意事项有哪些?比如不能创造新的运算符,不能改变运算符的优先级和结合性,还有某些运算符不能被重载,比如.和::。这些都需要提到,避免用户犯错误。 可能需要用示例代码来展示如何重载一个运算符,比如重载+号来实现复数的加法。同时,还要说明哪些运算符可以重载,哪些不行,以及常见的应用场景,比如字符串拼接、数学运算等。 另外,用户可能想知道运算符重载的优缺点。比如,优点是可读性高,缺点是过度使用可能导致代码难以理解。这点也应该提一下,帮助用户合理使用。 最后,是否需要提醒一些常见错误?比如重载&&和||时失去短路特性,或者重载赋值运算符时的深拷贝问题。这些高级话题可能用户暂时不需要,但可以简要提及,让他们有进一步学习的兴趣。 总之,结构应该是先定义,再作用,然后如何实现,包括成员函数和友元函数的区别,示例代码,注意事项,应用场景,最后优缺点。这样用户能逐步理解,从基础到应用都有所收获。</think>以下是对C++运算符重载的逐步解释: ===== 基础概念 ===== 运算符重载允许为自定义类型(类或结构体)定义运算符的特殊行为。通过重载运算符,可以使代码更直观,例如: $$Complex\ a(1,2),\ b(3,4);$$ $$Complex\ c = a + b; \ //直接使用+号代替Add()函数$$ ===== 重载方式 ===== 1. **成员函数重载**(推荐用于需要修改对象状态的运算符) ```cpp class Vector { public: Vector operator+(const Vector& other) { return Vector(x + other.x, y + other.y); } private: int x, y; }; ``` 2. **非成员函数重载**(常配合友元使用,适用于需要对称性的运算符) ```cpp class Complex { friend Complex operator+(const Complex& a, const Complex& b); }; Complex operator+(const Complex& a, const Complex& b) { return Complex(a.real + b.real, a.imag + b.imag); } ``` ===== 核心规则 ===== 1. 至少一个操作数必须是用户定义类型 2. 不能改变运算符的优先级和结合性 3. 不能创建新运算符(如**) 4. 部分运算符不可重载:`::`、`.`、`.*`、`?:`、`sizeof`等 ===== 典型应用示例 ===== 1. 输出流重载: ```cpp ostream& operator<<(ostream& os, const Student& s) { return os << "Name:" << s.name << " Age:" << s.age; } // 使用:cout << studentObj; ``` 2. 下标运算符重载: ```cpp class Array { public: int& operator[](int index) { return data[index]; } }; // 使用:arr[5] = 10; ``` ===== 注意事项 ===== 1. 赋值运算符`=`需要处理自赋值问题 2. 重载`&&`和`||`会失去短路特性 3. 运算符重载应保持语义一致性(例如`+`不应实现减法功能) 4. 特殊运算符需要成对重载(如`==`与`!=`,`<`与`>`) ===== 应用场景 ===== - 数学运算:复数、矩阵运算 - 容器类:自定义下标访问 - I/O操作:简化对象输入输出 - 智能指针:模拟指针行为 ===== 最佳实践 ===== 1. 优先选择成员函数形式重载`=`、`[]`、`()`、`->` 2. 对于需要隐式类型转换的运算符(如`+`),建议使用非成员函数 3. 保持运算符的数学/常规语义 4. 对于可能失败的运算(如除法),应通过异常或返回值处理错误 运算符重载C++多态性的重要体现,合理使用可以显著提升代码可读性,但需避免过度设计导致代码晦涩难懂。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值