05.了解C++默默编写并调用哪些函数

  • 编译产生的析构函数时non-virtual,除非这个类的基类析构函数为virtual
  • 成员变量中有引用和const成员时,无法自己主动生成copy assignment函数
  • 基类将copy assignment操作符声明为private时。编译器拒绝为其derived classes生成一个copy assignment操作符。

06.若不想使用编译器自己主动生成的函数,就该明白拒绝

  • 将自己主动生成的默认构造函数,拷贝构造函数,copy assignment声明为private
  • 声明为private并不绝对安全。成员函数和友元函数能够进行调用 -- 进行声明,但不定义(产生链接错误)
  • 定义一个基类。将默认构造函数,拷贝构造函数。copy assignment声明为private。由派生类继承该基类(产生编译错误。boost中的noncopyable类)

07.为多态基类声明virtual析构函数

  • 基类指针指向派生类时,delete基类指针,无法调用到派生类的析构函数
  • 不论什么class仅仅要带有virtual函数,应该有一个virtual析构函数。

  • 当class不含virtual函数,通常表示它并不意图被用作一个base class。
  • 当class不企图被当做base class。其析构函数为virtual往往是个馊主意。(占用空间,减少效率)

08.别让异常逃离析构函数

  • 析构函数未捕获异常时,假设该类对象存储于容器中。产生异常后可能导致容器中的其它对象无法析构。
  • 析构函数须要捕获异常,某些引发异常的操作可移出析构,由客户调用进行处理

09.绝不在构造和析构中调用virtual函数

  • base class构造期间。virtual函数绝不会下降到derived class阶层。构造期间。virtual函数不是virtual函数。

  • 当base class构造函数运行时derived class成员变量尚未初始化,假设下降到derived class,derived class将会使用为初始化的local成员变量。

  • derived class对象的base class构造期间。对象的类型时base class。
  • 一旦derived class析构函数開始运行,进入base class析构函数后,对象类型被视为base class。

10.令operator=返回一个reference to *this

为了实现连锁赋值,赋值操作符必须返回一个reference指向操作符左側实參。

仅仅是协议,并不是强制。

Widget& operator=(const Widget& rhs) {return  *this;}

问题:

能否够返回常量引用?

11.在operator= 中处理自我赋值

  • 须要解决自我赋值安全性和异常安全性

class Bitmap {...};
class Widget {
private:
Bitmap* pb;
}; Widget& Widget::operator=(const Widget& rhs)
{
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
};

  • 以上代码问题:当自我赋值时,将删除自身的pb。构造新bp时。使用一个已删除的对象。

    解决方法例如以下:

Widget& Widget::operator=(const Widget& rhs)
{
if (this == &rhs)
return *this;
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}

  • 以上代码存在问题:new Bitmap导致异常时,pb指向一个已删除的区域。解决方法例如以下:
Widget& Widget::operator=(const Widget& rhs)
{
if (this == &rhs)
return *this; Bitmap* pOrig = pb;
pb = new Bitmap(*rhs.pb);
delete pOrig;
return *this;
}

12.复制对象时勿忘其每个成分

  • 新加入成员变量时须要改动复制构造函数,copy assignment函数。

class PriorityCustomer: public Customer {
public:
PriorityCustomer(const PriorityCustomer& rhs);
PriorityCustomer& operator=(const PriorityCustomer& rhs);
private:
int priority;
}; PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):priority(rhs.priority)
{
log("");
} PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
log("");
priority = rhs.priority;
return *this;
}

  • 以上代码问题:未调用基类的拷贝构造函数,未调用基类的赋值操作符重载函数。正确代码例如以下:

PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):Customer(rhs),priority(rhs.priority)
{
log("");
} PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
log("");
Customer::operator(rhs);
priority = rhs.priority;
return *this;
}

  • 无法在拷贝构造函数中调用基类的赋值操作符重载。无法在赋值操作符重载函数中调用基类的拷贝构造函数。

Effective C++ -- 构造析构赋值运算的更多相关文章

  1. Effective C++ —— 构造/析构/赋值运算(二)

    条款05 : 了解C++默默编写并调用哪些函数 编译器可以暗自为class创建default构造函数.copy构造函数.copy assignment操作符,以及析构函数. 1. default构造函 ...

  2. 《Effective C++》第2章 构造/析构/赋值运算(2)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  3. 《Effective C++》第2章 构造/析构/赋值运算(1)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  4. EffectiveC++ 第2章 构造/析构/赋值运算

    我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 2 构造 / 析构 / 赋值 条款 05:了解C++ ...

  5. Effective C++ 笔记二 构造/析构/赋值运算

    条款05:了解C++默默编写并调用哪些函数 编译器默认声明一个default构造函数.一个copy构造函数.一个copy assignment操作符和一个析构函数.这些函数都是public且inlin ...

  6. Effective C++笔记:构造/析构/赋值运算

    条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函 ...

  7. Effective C++笔记(二):构造/析构/赋值运算

    参考:http://www.cnblogs.com/ronny/p/3740926.html 条款05:了解C++默默编写并调用哪些函数 如果自定义一个空类的话,会自动生成默认构造函数.拷贝构造函数. ...

  8. 【Effective C++】构造/析构/赋值运算

    条款05:了解C++默默编写并调用哪些函数 默认构造函数.拷贝构造函数.拷贝赋值函数.析构函数构成了一个类的脊梁,只有良好的处理这些函数的定义才能保证类的设计良好性. 当我们没有人为的定义上面的几个函 ...

  9. Effective C++ 2.构造 析构 赋值运算

    //条款07:为多态基类声明virtual析构函数 // 1.若基类的析构函数不定义为虚函数,由于基类的指针或引用可以指向派生类的对象,则在删除基类对象的时候可能会出错,导致破坏数据结构. // 2. ...

随机推荐

  1. html5的自定义data-*属性和jquery的data()方法的使用

    人们总喜欢往HTML标签上添加自定义属性来存储和操作数据.但这样做的问题是,你不知道将来会不会有其它脚本把你的自定义属性给重置掉,此外,你这样做也会导致html语法上不符合Html规范,以及一些其它副 ...

  2. 【每日一摩斯】-Troubleshooting: High CPU Utilization (164768.1) - 系列4

    Jobs (CJQ0, Jn, SNPn) Job进程运行用户定义的以及系统定义的类似于batch的任务.检查Job进程占用大量CPU资源的方法,就像检查用户进程一样. 可以根据以下视图检查Job进程 ...

  3. 【AllJoyn专题】基于AllJoyn和Yeelink的传感器数据上传与指令下行的研究

    接触高通物联网框架AllJoyn不太久,但确是被深深地吸引了.在我看来,促进我深入学习的原因有三点:一.AllJoyn开源,对开源的软硬件总会有种莫名的喜爱,虽然或许不会都深入下去:二.顺应潮流,物联 ...

  4. 利用Android属性动画实现Banner的原理与实践

    事实上在Android刚推出属性动画的时候.就想利用它来设计一个Banner控件,一直没什么时间尝试. 在当时看我们应用中的Banner,使用计时器来控制自己主动播放,设置一个非常大的数,利用余数原理 ...

  5. 内省(二)之BeanUtils工具类

    上一篇内省(Introspector)讲到的是采用JavaAPI中的类来操作bean及其属性,而Apache也开源了第三方框架来简化和丰富了对bean属性的操作,这个框架就是BeanUtils. 使用 ...

  6. 一些关于Console的API函数

    SetConsoleCtrlHandlerGenerateConsoleCtrlEventSetConsoleMode ReadConsole WriteConsole SetConsoleCP Se ...

  7. 【ASP.NET Web API教程】2.1 创建支持CRUD操作的Web API

    原文 [ASP.NET Web API教程]2.1 创建支持CRUD操作的Web API 2.1 Creating a Web API that Supports CRUD Operations2.1 ...

  8. iText 文本

    iText中用文本块(Chunk).短语(Phrase)和段落(paragraph)处理文本. 文本块(Chunk)是处理文本的最小单位,有一串带格式(包括字体.颜色.大小)的字符串组成.如以下代码就 ...

  9. 让MFC程序隐藏运行界面

    在MFC中隐藏运行界面确实花花点功力. 针对对话框程序,一种不是很好地实现方法是在OnPaint函数中添加如下代码: CWnd::ShowWindow(SW_HIDE); 添加后执行会发现屏幕会闪烁一 ...

  10. 对数的操作 开始我的JAVA历程

    package Text; public class Sumn { public static void main (String args[]){ System.out.println(" ...