赋值重载
赋值重载运算符: 类名 & operator=(const 类名& 变量名)
一个空类中至少有四个函数:无参构造函数、拷贝构造函数、析构函数、赋值运算符重载函数
#include <iostream>
#include <string.h>
using namespace std;
class Student
{
public:
Student(int id = 0, char *name = NULL)
{
this->id = id;
this->name = name;
}
void show()
{
printf("id = %id, name = %s\n", id, name);
}
/*赋值运算符: 类名& operator=(const 类名 &变量名)
Student& operator=(const Student &s)
{
id = s.id;
name = s.name;
return *this;
}
如果不写,编译器会自动生成
*/
private:
int id;
char *name;
};
int main1()
{
Student s1(1, "小明");
s1.show();
Student s2 = s1;//拷贝构造
Student s3;
/*s3 = s1 是赋值 operator=(s3, s1)======> s3.operator=(s1)
如果一个类没有写赋值运算符重载函数,则编译器会自动生成一个
赋值运算符重载函数来做值的赋值
*/
s3 = s1;
s2.show();
s3.show();
//可将s2 = s1看作一个整体a ====》s3.operator=(a) a ==== s2.operator=(s1)
//最终形式:s3.operator=(s2.operator=(s1))
s3 = s2 = s1;
s1.show();
s2.show();
s3.show();
return 0;
}
class Teacher
{
friend ostream& operator<< (ostream& out, Teacher &t);
public:
Teacher(int id, char *name)//构造函数
{
this->id = id;
this->name = new char[20];
strcpy(this->name, name);
}
Teacher(const Teacher &t)//拷贝构造函数
{
this->id = t.id;
this->name = new char[20];
strcpy(this->name, t.name);
}
~Teacher()//析构函数
{
if (name != NULL)
delete[] name;
name = NULL;
id = 0;
}
/*存在的问题,如果自己给自己赋值则存在会丢失原来空间内的值
Teacher& operator=(const Teacher &t)
{
//0.判断是否是对象本身
if (this == &t)
return *this;
//1.释放原来的空间
if (name != NULL)
delete[] name;
//2.开辟新空间
this->name = new char[20];
//3.复制数据
this->id = t.id;
strcpy(this->name, t.name);
return *this;
}
*/
//正确赋值重载(涉及空间)
Teacher& operator=(const Teacher &t)
{
//0.判断是否是对象本身
if (this == &t)
return *this;
//1.创建临时对象
Teacher tmp = t; //拷贝构造
//2.交换空间
char *p = tmp.name;
tmp.name = name;
name = p;
//3.复制其他数据
id = tmp.id;
return *this;
}
private:
int id;
char *name;
};
// 重载<<,实现直接输出Teacher类的内容
ostream& operator<< (ostream& out, Teacher &t)
{
out << "id = " << t.id << ", name = " << t.name;
return out;
}
int main2()
{
Teacher t1(1, "小明");
cout << t1 << endl;
Teacher t2 = t1;//调用拷贝构造
cout << t2 << endl;
Teacher t3(2, "小红");
//默认的赋值运算符重载函数做的也是浅拷贝,
//涉及到空间的操作需要自定义赋值运算符重载函数
t3 = t1; //赋值操作
cout << t3 << endl;
t3 = t3;
cout << t3 << endl;
return 0;
}
与拷贝构造一样不要轻易地写赋值重载,一般将赋值运算符和拷贝重载设为私有,形式如下
class A
{
private:
A(const A&);//拷贝构造
A& operator=(const A&);//赋值重载
};
逻辑运算符重载
不要重载逻辑运算符,重载了也不会达到想要的效果
1)&&和||是C++中非常特殊的操作符2)&&和||内置实现了短路规则
3)操作符重载是靠函数重载来完成的
4)操作数作为函数参数传递
5)C++的函数参数都会被求值,无法实现短路规则
#include <iostream>
using namespace std;
int main4()
{
int a = 0;
int b = 1;
int c = 2;
//逻辑运算符内部实现了短路原则:(&&)左边为假右边不用执行,直接返回bool值假,(||)左边为真右边不用执行,直接返回bool值真
a && (b = c);
b || (a = c);
cout << "a = " << a << endl;// 0
cout << "b = " << b << endl;// 1
cout << "c = " << c << endl;// 2
return 0;
}
class A
{
public:
A(int a)
{
this->a = a;
}
bool operator&&(const A& a)
{
return a.a && this->a;
}
public:
int a;
};
//不要重载逻辑运算符
int main5()
{
A a = 0;
A b = 1;
A c = 2;
/*逻辑运算符内部实现了短路原则
a.operator&&(b = c)
运算符重载本质上是一个函数,函数要先计算实参的值,再将实参传给形参
所以无法实现短路原则,和原先的意义不符
*/
a && (b = c);
cout << "a = " << a.a << endl;// 0
cout << "a = " << b.a << endl;// 2,先完成赋值语句 b = c,再调用&&重载函数
cout << "a = " << c.a << endl;// 2
return 0;
}