技术
探寻C++类 —— 重载赋值操作符 (operator=)
已经忙碌一个多月,现在才想起来要更博了。今天在写课堂实验时,一题为:
编写一个程序:输入几个学生的姓名、英语和计算机成绩,然后按照总分从高到低排序。要求定义一个Student类,并用友元函数实现排序。
开始看到这题觉得还是挺简单的,其中排序是常见的冒泡排序。众所周知,冒泡排序中,需要建立一个缓存变量来交换变量。而在此例中,需要交换的是类对象,那么解决方法则有两种:
第一种方法是使用一个自定义的equal函数
void equal(Student &a,Student &b)
{
strcpy(a.name,b.name); // require include <string>
a. englishScore = b. englishScore;
a. computerScore = b. computerScore;
a. totalScore = b. totalScore;
}
第二种方法则是使用运算符重载,这里则需要重载赋值操作符(operator=)
刚使用重载赋值操作符时,在函数中创建新对象,处理完后返回新对象的引用,结果发现这样做是十分危险而且是错误的。
查阅CSDN和书籍,对于赋值操作符=的重载有如下说明:
string& operator=(const string&);// s1=s2
string& operator=(const char *);// s1="str"
string& operator=(char);// s1='c'
需要注意的是:无论形参为何种类型,赋值操作符必须定义为成员函数,且必须返回对*this的引用。
因而得到以下函数体:
MyClass& MyClass::operator=(const MyClass &T)
{
// do something
}
但上述函数体仍不完善,例如a=a时会出现什么情况?还有需要考虑性能问题。
为了防止自身赋值,需要判断一下:
MyClass& MyClass::operator=(const MyClass &T)
{
if (this == &T)
return *this;
// do something
return *this;
}
结合题目,可写出如下重载函数:
Student& Student::operator=(const Student &T)
{
if (this == &T)
return *this;
strcpy(name, T.name); // require include <string>
englishScore = T.englishScore;
computerScore = T.computerScore;
totalScore = T.totalScore;
return *this;
}
通过实验,发现使用重载操作符会比使用equal函数更方便,从而整理出重载操作符的一些规则供以后学习使用。
- 除了函数调用操作符之外,重载操作符的形参数目(包括成员函数的隐式this指针)与操作符的操作数数目相同。
- 形参值要为const类型。
- 返回一个引用,以便于实现a=b=c。
- &&、&、||和,等操作符最好不要重载。
- 类一般都需重载输入/输出操作数,IO操作符必须为非成员符,所以类常将其设为友元。
- 作为成员函数的操作符有一个隐含的this形参,限定为第一个操作数。
- 重载操作符必须具有至少一个类类型的操作数。