《Effective c++》Chapter2 读书笔记

Chapter2

条款05:了解C++默默编写并调用哪些函数
  • 编译器可以暗自为class创建default构造函数,copy构造函数,copy assignment操作符,以及构造函数
  • 编译器产出的析构函数是个non-virtual,除非这个classbase class自身声明有virtual析构函数
  • copy assignmet函数被编译器默认构造出来需要满足以下条件
    1. 不包含reference成员和const成员
    2. 某个base classescopy assignment操作符声明为private,编译器将拒绝为其derived classes生成一个copy assignment操作符
条款06:若不想使用编译器自动生成的函数,就该明确拒绝
  • 为驳回编译器自动(暗自)提供的机能,可将相应的成员函数声明为private并且不予实现。(见下例)
//例子:阻止类被拷贝

//阻止编译器自动生成函数的方法一

//将成员函数声明为`private`
class HomeForSale{
    public:
        ...
    private:
        ...
        HomeForSale(const HomeForSale&);    //只有声明不实现
        HomeForSale& operator=(const HomeForSale&);
};


//方法二
//可能有很多类需要阻止,所以可以声明一个统一的类
class Uncopyable{
    protected:
        Uncopyable() {}
        ~Uncopyable() {}
    private:
        Uncopyable(const Uncopyable&);
        Uncopyable& operator=(const Uncopyable&);
};

//class不在声明copy构造函数和copy assign操作符
class HomeForSale:private Uncopyable{
    ...
};
条款07:为多态基类声明virtual析构函数
  • 带多态性质的base classes应该声明一个virtual析构函数
  • 只有当class内含至少一个virtual函数,才为它声明virtual析构函数
  • classes的设计目的如果不是作为base class使用,或不是为了具备多态性,就不应该声明virtual析构函数

无端将所有析构函数都声明为virtual会造成资源的浪费

条款08:别让异常逃离析构函数
  • 若析构函数为正确处理异常导致异常跳出析构函数,则程序无法正常析构对象
  • 析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序。
  • 如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作.(见下例)
class DBCnn{
    public:
        ...
        //给客户提供一个自行选择的close()函数
        void close(){
            db.close();
            closed=true;
        }
        ~DBCnn(){
            if(!closed){
                try{
                    db.close();
                }
                catch(...){
                    制作运转记录,记下对close的调用失败
                    ...
                }
            }
        }
    private:
        DBConnection db;
        bool closed;
};
条款09:绝不在构造和析构过程中调用virtual函数
  • 在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived calss
  • derived class对象的base class构造期间,对象的类型是base class而不是derived class,所以此时virtual函数会被编译器解析为base class
条款10:令operator=返回一个reference to *this
  • 令赋值(=,+=,-=,*=等)操作返回一个reference to *this
条款11:在operator=中处理"自我赋值"
  • operator=中需要特别注意"自我赋值",传统的做法是加上一个"证同测试"(见下例)
class Bitmap{...};
class Widget{
    ...
    private:
        Bitmap* pb;
};
Widge& Widget::operator=(const Widget& rhs){
    //证同测试
    if(this==&rhs) return *this;

    delete pb;
    pb=new Bitmap(*rhs.pb);
    return *this;
}
条款12:复制对象时勿忘其每一个成分
  • 当编写一个copying函数,请确保:
    1. 复制所有local成员变量
    2. 调用所有base classes内的适当的copying函数
  • 永远不要令copy assignment操作符调用copy构造函数,同理,不要令copy构造函数调用copy assignment操作符
  • copy构造函数和copy assignment操作符含有相近的代码,消除重复代码的做法是,建立一个新的成员函数给两者调用。(这样的函数往往是private而且常被命名为init
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值