一、重载赋值运算符“=”

赋值运算符“=”要求左右两个操作数的类型是匹配的,或至少是兼容的。有时候希望赋值运算符两边的类型可以不匹配,比如,把一个int类型变量赋值给一个Complex对象,或把一个 char * 类型的字符串赋值给一个字符串对象,此时就需要重载赋值运算符“=”。C++规定,赋值运算符“=”只能重载为成员函数。

程序示例分析:

#include<iostream>
using namespace std;
class String {
private:
char* str;
public:
String() :str(new char[]) { str[] = ; }
const char* c_str() { return str; };
String& operator = (const char* s);
String::~String() { delete[] str; }
};
String& String::operator = (const char* s)
{ //重载“=”以使得 obj = “hello”能够成立
delete[] str;
str = new char[strlen(s) + ];
strcpy(str, s);
return *this;
}
int main()
{
String s;
s = "Good Luck,"; //等价于 s.operator=("Good Luck,");
cout << s.c_str() << endl;
// String s2 = "hello!"; //这条语句要是不注释掉就会出错
s = "Shenzhou 8!"; //等价于 s.operator=("Shenzhou 8!");
cout << s.c_str() << endl;
return ;
}

输出结果:

Good Luck,
Shenzhou !

二、浅拷贝和深拷贝

同类对象之间可以通过赋值运算符“=”互相赋值。如果没有经过重载,“=”的作用就是把左边的对象的每个成员都变得和右边的对象相等,即执行逐个字节拷贝的工作,这种拷贝叫作“浅拷贝” 。

经过重载,赋值号“=”的功能不再是浅拷贝,而是将一个对象中指针成员变量指向的内容复制到另一个对象中指针成员变量指向的地方,这种拷贝叫作“深拷贝” 。

class String {
private:
char* str;
public:
String() :str(new char[]) { str[] = ; }
const char* c_str() { return str; };
String& operator = (const char* s) {
delete[] str;
str = new char[strlen(s) + ];
strcpy(str, s);
return *this;
};
~String() { delete[] str; }
};

按照这个String类的写法,下面的程序片段会引发问题

String S1, S2;
S1 = “this”;
S2 = “that”;
S1 = S2;

如不定义自己的赋值运算符,那么S1=S2实际上导致 S1.str和 S2.str指向同一地方。

如果S1对象消亡,析构函数将释放 S1.str指向的空间,则S2消亡时还要释放一次,不妥。

另外,如果执行 S1 = "other";会导致S2.str指向的地方被delete

因此要在 class String里添加成员函数:

String & operator = (const String & s) {
delete [] str;
str = new char[strlen( s.str)+];
strcpy( str,s.str);
return * this;
}

Question1:

考虑下面语句是否会有问题?

String s;
s = "Hello";
s = s;

解决办法:

解决办法:
String & operator = (const String & s){
if( this == & s)
return * this;
delete [] str;
str = new char[strlen(s.str)+];
strcpy( str,s.str);
return * this;
}

Question2:

对 operator = 返回值类型的讨论

void 好不好?

String 好不好?

为什么是 String &

对运算符进行重载的时候,好的风格是应该尽量保留运算符原本的特性

考虑

a = b = c;

(a=b)=c; //会修改a的值

分别等价于:

a.operator=(b.operator=(c));
(a.operator=(b)).operator=(c);

Question3:

上面的String类是否就没有问题了?

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

String( String & s)
{
str = new char[strlen(s.str)+];
strcpy(str,s.str);
}

Question4:

以下说法正确的是:

A) 成员对象都是用无参构造函数初始化的

B) 封闭类中成员对象的构造函数先于封闭类的构造函数被调用

C) 封闭类中成员对象的析构函数先于封闭类的析构函数被调用

D) 若封闭类有多个成员对象,则它们的初始化顺序取决于封闭类构造函数中的成员初始化列表

《新标准C++程序设计》4.2-4.3(C++学习笔记13)的更多相关文章

  1. 《新标准C++程序设计》4.5(C++学习笔记15)

    实例:长度可变的整型数组类 int main() { //要编写可变长整型数组类,使之能如下使用: CArray a; //开始里的数组是空的 ; i < ; ++i) a.push_back( ...

  2. 《新标准C++程序设计》4.6(C++学习笔记16)

    重载流插入运算符和流提取运算符 流插入运算符:“<<” 流提取运算符:“>>” cout 是在 iostream 中定义的,ostream 类的对象. “<<” 能 ...

  3. 《新标准C++程序设计》4.4(C++学习笔记14)

    运算符重载为友元函数 一般情况下,将运算符重载为类的成员函数,是较好的选择. 但有时,重载为成员函数不能满足使用要求,重载为普通函数,又不能访问类的私有成员,所以需要将运算符重载为友元. class ...

  4. 《新标准C++程序设计》4.1(C++学习笔记12)

    运算符重载的概念和原理 一.运算符重载的需求 C++预定义的“+.-. * ./.%. ^ .&.~.!.|. = .<< >>.!= ”等运算符,只能用于基本数据类型 ...

  5. 《新标准C++程序设计》3.8(C++学习笔记10)

    友元 友元分为友元函数和友元类两种. 一.友元函数 在定义一个类的时候,可以把一些函数(包括全局函数和其它类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对 ...

  6. 《新标准C++程序设计》3.5(C++学习笔记8)

    常量对象和常量成员函数 一.常量对象 如果希望某个对象的值初始化后就再也不被改变,则定义该对象时可以在前面加const关键字,使之成为常量对象. class CDemo { private: int ...

  7. JavaScript高级程序设计(第三版)学习笔记13、14章

    第13章,事件 事件冒泡 IE的事件叫做事件冒泡:由具体到不具体 <!DOCTYPE html> <html> <head>      <title>E ...

  8. 正确处理类的复合关系------新标准c++程序设计

    假设要编写一个小区养狗管理程序,该程序需要一个“主人”类,还需要一个“狗”类.狗是有主人的,主人也有狗.假定狗只有一个主人,但一个主人可以有最多10条狗.该如何处理“主人”类和“狗”类的关系呢?下面是 ...

  9. 在成员函数中调用虚函数(关于多态的注意事项)------新标准c++程序设计

    类的成员函数之间可以互相调用.在成员函数(静态成员函数.构造函数和析构函数除外)中调用其他虚成员函数的语句是多态的.例如: #include<iostream> using namespa ...

  10. 多态实现的原理------新标准c++程序设计

    “多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定.例子: #include<iostream> using namespac ...

随机推荐

  1. tf.reduce_max 与 reduce 系列 API

    reduce 可以理解为 python 里的 reduce 函数: tensorflow 中有很多 reduce_ API,其用法完全相同 tf.reduce_max 以这个为例进行说明 def re ...

  2. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 排版:设定单词首字母大写

    <!DOCTYPE html> <html> <head> <title>菜鸟教程(runoob.com)</title> <meta ...

  3. Ionic3记录之核心代码分析

    app.module.ts app的根模块,一些插件的引用需要在这里声明,告诉APP如何组装应用: app.componet.ts app的根组件,主要用来APP启动时和启动后的操作;

  4. HTML 5 <em> <strong> <dfn> <code> <samp> <kbd> <var> <cite> 标签

    <em> 呈现为被强调的文本. <strong> 定义重要的文本. <dfn> 定义一个定义项目. <code> 定义计算机代码文本. <samp ...

  5. Day11 - M - Nim or not Nim? HDU - 3032

    Nim is a two-player mathematic game of strategy in which players take turns removing objects from di ...

  6. Python简单程序爬取天气信息,定时发邮件给朋友【高薪必学】

    前段时间看到了这个博客.https://blog.csdn.net/weixin_45081575/article/details/102886718.他用了request模块,这不巧了么,正好我刚用 ...

  7. 113、Java中String类之字符串文本分割IP地址

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  8. sqlserver链接字符串

    string connectionStr = "Data Source=LJJ-FF\\LJJ;Initial Catalog=TestDapper;User ID=sa;Password= ...

  9. windows系统 安装与配置zabbix-agent

    1.下载安装包 http://192.168.130.150/zabbix/zabbix_agent-4.0.12-win-amd64-openssl.msi 下载包的链接地址 windowszabb ...

  10. HDU 5506:GT and set bitset+暴力

    GT and set  Accepts: 35  Submissions: 194  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 655 ...