当前位置:编程学习 > VB >>

C++ 什么情况下需要为类定义赋值运算符重载函数?

补充:注意 是【赋值】运算符重载。
(在这道题前面有个类似的问题,是什么情况下要定义拷贝构造函数。
我觉得这两个问题应该有联系的。)
答案:
使程序更加简洁,减少编程时间,让自己容易理解。
看下面一个表示string对象的类:

// 一个很简单的string类
class string {
public:
string(const char *value);
~string();

... // 没有拷贝构造函数和operator=

private:
char *data;
};

string::string(const char *value)
{
if (value) {
data = new char[strlen(value) + 1];
strcpy(data, value);
}
else {
data = new char[1];
*data = '\0';
}
}

inline string::~string() { delete [] data; }

请注意这个类里没有声明赋值操作符和拷贝构造函数。这会带来一些不良后果。

如果这样定义两个对象:

string a("hello");
string b("world");

其结果就会如下所示:

a: data——> "hello\0"
b: data——> "world\0"

对象a的内部是一个指向包含字符串"hello"的内存的指针,对象b的内部是一个指向包含字符串"world"的内存的指针。如果进行下面的赋值:

b = a;

因为没有自定义的operator=可以调用,c++会生成并调用一个缺省的operator=操作符(见条款45)。这个缺省的赋值操作符会执行从a的成员到b的成员的逐个成员的赋值操作,对指针(a.data和b.data) 来说就是逐位拷贝。赋值的结果如下所示:

a: data --------> "hello\0"
/
b: data --/ "world\0"

这种情况下至少有两个问题。第一,b曾指向的内存永远不会被删除,因而会永远丢失。这是产生内存泄漏的典型例子。第二,现在a和b包含的指针指向同一个字符串,那么只要其中一个离开了它的生存空间,其析构函数就会删除掉另一个指针还指向的那块内存。

string a("hello"); // 定义并构造 a

{ // 开一个新的生存空间
string b("world"); // 定义并构造 b

...

b = a; // 执行 operator=,
// 丢失b的内存

} // 离开生存空间, 调用
// b的析构函数

string c = a; // c.data 的值不能确定!
// a.data 已被删除

例子中最后一个语句调用了拷贝构造函数,因为它也没有在类中定义,c++以与处理赋值操作符一样的方式生成一个拷贝构造函数并执行相同的动作:对对象里的指针进行逐位拷贝。这会导致同样的问题,但不用担心内存泄漏,因为被初始化的对象还不能指向任何的内存。比如上面代码中的情形,当c.data用a.data的值来初始化时没有内存泄漏,因为c.data没指向任何地方。不过,假如c被a初始化后,c.data和a.data指向同一个地方,那这个地方会被删除两次:一次在c被摧毁时,另一次在a被摧毁时。
运算符重载是为了得到特定运算方法而编写的一个函数,比如说复数的相加是不能够直接用一个+就能算出来的,需要编写很多细节的部分,像实部虚部要分别相加处理才行,这时用运算符重载的话,就可以直接用一个符号就能实现这个操作,从而达到了简洁的目的。

上一个:vb 数据库问题
下一个:vb高手问题

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,