重载赋值运算符(解决指针悬挂)
—— (与拷贝构造函数结合起来理解)
c++中,对于任何一个类,如果没有用户自定义的赋值运算符函数,系统会自动的为其生成一个默认的赋值运算符函数,以完成数据成员之间的逐位复制。通常情况下,默认的赋值运算符函数可以完成赋值任务,但在类中含有指针的特殊情况下,就不能直接互相赋值,因为有可能造成指针悬挂。
指针悬挂问题
解决方法:重载赋值运算符解决指针悬挂问题
引出一个简单的例子:
#include<iostream>
#include<cstring>
using namespace std;
class Student
{
private:
char *name ;
int num;
public:
Student(char *na, int n)
{
name = new char[strlen(na) + 1];
strcpy(name, na);
num = n;
}
Student &operator=(const Student &p)
{
//判断是不是p1给自己赋值 避免p1=p1的赋值
if (this == &p)
return *this;
delete[] name;
name = new char[strlen(p.name) + 1];
strcpy(name, p.name);
num = p.num;
return *this;
}
~Student()
{
delete[] name;
}
void Print()
{
cout << name << " " << num << endl;
}
};
int main()
{
Student p1("zhang", 5);
Student p2("wang", 6);
cout << " p2: ";
p2.Print();
p2 = p1;
cout << "修改后p2: ";
p2.Print();
return 0;
}
运行结果
p2:wang 6
修改后p2:zhang 5
可见已经完成的赋值过程,如图解:
注意:
(1)赋值运算符不能重载为友元函数,只能重载为一个非静态成员函数。这是由于考虑了c++的封装性和数据的安全性。一般而言,用友元函数重载比用成员函数重载更便于使用。
(2)赋值运算符不能被继承。
拷贝构造函数
c++不仅可以用构造函数来创建对象,也可以通过已有对象创建新对象。可用一个已有对象来给另一个对象赋值,对象进行赋值时,对象的每一个成员逐一复制给另一个对象的同一成员。所以,在有类对象的传值情况下需要用到拷贝构造函数。在参数传递的过程中,是由实参将自己的值复制了一份传给形参,采用按位拷贝的方式,所以在传递的过程中,并不会再创建一个新的类对象。为了防止一个对象不被通过传值方式传递,需要声明一个私有的拷贝构造函数。
注意: 拷贝构造函数的定义格式如下:只能使用引用的方式,原因是防止无限递归调用。
构造函数名(const 类名&)
在拷贝函数和重载赋值运算符函数同时存在的情况下,会直接调用赋值运算符函数。