zoukankan      html  css  js  c++  java
  • Effective C++ 笔记(2)构造/析构/赋值运算

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

      (1)、默认构造函数

    Empty(){...} //调用父类构造函数,non-static成员变量构造函数,不会默认初始化内置类型

      (2)、析构函数

    ~Empty(){...} //调用父类析构函数,non-static成员变量析构函数

      (3)、拷贝构造函数

    Empty(const Empty& rhs){...} //单纯地将来源对象的每一个non-static变量拷贝到目标对象

      (4)、赋值构造函数

    Empty& operator=(const Empty& rhs){...} //单纯地将来源对象的每一个non-static变量拷贝到目标对象

      类内有引用、const、及父类的拷贝构造函数,赋值构造函数为private时,编译器会拒绝生成这一类函数。换言之,如果类内有引用、const成员变量,或者其父类的相关函数不可访问时,必须手动生成。有指针类型变量时,存在“深拷贝、浅拷贝”问题!!!

    class Empty:
    {
    public:
        Empty(){...}
        Empty(const Empty& rhs){...}
        ~Empty(){...}
        
        Empty& operator=(const Empty& rhs){...}
    private:
        const int m_cInt; //只读成员变量
        int &ref; //引用型成员变量,必须在每个构造函数手动初始化
    };
    

      

    06、若不想使用编译器自动生成的函数,就该明确拒绝

    禁止被拷贝构造或赋值构造的做法:

      (1)、将相应成员函数声明为private且不去实现它。(链接期出错

    class HomeForSale
    {
    public:
        HomeForSale();
        ~HomeForSale();
    private:
        HomeForSale(const HomeForSale& rhs);    //只有声明
        HomeForSale& operator=(const HomeForSale& rhs);    
    };
    

      (2)、private继承Uncopyable类(编译期出错)

    class Uncopyable
    {
    public:
        Uncopyable(){};
        ~Uncopyable(){};
    private:
        Uncopyable(const Uncopyable& rhs);
        Uncopyable& operator=(const Uncopyable& rhs);
    };
    

      

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

      (1)、polymorphic(带多态性质的)base classes应该声明一个virtual析构函数,这样通过delete 基类指针时,也会调用其指向对象的析构函数。避免内存泄漏。如果一个class带有一个或多个virtual函数,它就应该拥有一个virtual析构函数。

      (2)、classes的设计目的如果不是作为base classes使用,或不是为了具备多态性,就不应该声明virtual函数。(会多出一个vptr指针,占用内存),string及STL容器均为无virtual函数!尽量别继承它们做事。

      引申:c++11中可以override,final关键字指定。只能作用于虚函数

      override,表示此虚函数必定“重写”了基类中的对应虚函数。  

      final,(1)作用在虚函数:表示此虚函数已处在“最终”状态,后代类必定不能重写这个虚函数。  

           (2)作用在类:表示此类必定不能被继承 

      编译器将帮你检查是否“必定” 

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

      (1)、析构函数绝对不要抛出异常,如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后处理它们,或者结束程序;

      (2)、如果接口使用者需要对某个操作函数运行期间抛出的异常作出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作;

    class DBConn
    {
    public:
        void close()
        {
            db.close()//可能抛出异常函数
            closed = true;
        }
        ~DBConn()
        {
            if (!closed) //如果客户没有主动关闭的话
            {
                try
                {
                    db.close();
                }
                catch(...)
                {
                    //制作运转记录,记下对close的调用失败
                }
                /* code */
            }
        }
    private:
        DBConnection db;
        bool closed;
    };
    

    09、不要在构造和析构过程中调用virtual函数

    class Transaction //基类
    {
    public:
        Transaction();
        ~Transaction();
        virtual void logTransaction const = 0;
    };
    Transaction::Transaction()
    {
        ...
        logTransaction();//记录这笔交易
    }
    
    class BuyTransaction : public Transaction
    {
    public:
        BuyTransaction();
        ~BuyTransaction();
        virtual void logTransaction()const override; //记录这笔交易
    };
    

      BuyTransaction b;时先执行Transaction::Transaction,此时传入的this指针为Transaction* 故调用的是Transaction::logTransaction(),此时BuyTransaction还没被构造出来。

      构造函数:base::base-->derive::derive

      析构函数:base::~base-->derive::~derive

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

      用于链式赋值

    11、在operator= 中处理“自我赋值”

      推荐做法:

    Widget& Widget::operator=(Widget rhs)
    {
        swap(rhs); //成员函数,进行交换
        return *this;
    }

      (1)、确保当对象进行自我赋值时operator=有良好的行为。包括考虑“来源对象”和“目标对象”的地址(是否为同一个)、精心周到的语句顺序、以及复制交换;

      (2)、当一个函数操作多个对象时,确保即使这些对象为同一个对象,其行为仍然正确。

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

      (1)、Copying函数应该确保复制“对象内的所有成员变量”及“所有base class”成分;

      (2)、不要用某个copying函数实现另一个copying函数。应该将共同的代码放进第三个函数中,并由两个copying函数共同调用。

  • 相关阅读:
    mysql8.0 一次性备份导出/导入恢复所有数据库
    访问服务器共享资源不需要输帐号和密码
    win7 系统 提示用户'sa'登录失败
    Adoquery.disablecontrols和enablecontrols
    DBGridEh 导出数据到EXCEL文件
    Microsoft SQL Server 2005资料库(数据库)卸载方法
    64位操作系统下创建组件失败的解决办法
    U盘中的文件为什么看不见?
    解决错误提示unable to invoke code completion due to errors in source cord.
    浪潮服务器Windows Server系统异常断电导致系统中CentOS7虚拟机系统崩溃无法正常启动grub2故障修复error: relocation 0x48 is not implemented yet
  • 原文地址:https://www.cnblogs.com/quehualin/p/9209074.html
Copyright © 2011-2022 走看看