effective c++ 笔记 (9-12)

//---------------------------15/03/29----------------------------


//#9    绝不在构造和析构过程中调头virtual函数

{

   /*

        1:在构造时调用virtual函数有两个结果

            1>如果基类实现了这个函数,就调用基类的函数。

            2>基类没有实现这个函数,链接时报错。

            原因:

            1>基类的构造函数是早于 派生类的构造函数调用的,所以如果virtual函数使用派生类版本的

            话,很可能用到未初始化的派生类的成员变量。c++为了不让你走这条危险的路,就会只调用基类的版本

            2>根本原因:在调用基类构造函数时,对象类型是base class所以会调用基类版本。

            所以不要在构造函数中调用任何virtual函数。

        2:在析构函数中调用vitual函数:

            由于派生类的析构函数是先于基类调用的,所以轮到基类的构造函数时,派生类的成员变量依旧呈现

            未定义状态。所以c++视它们不存在,在调用基类析构函数时,对象称为一个base class对象。

        3:为了在派生类对象创建时,基类中有适当版本的显示信息调用,一个解决办法是由派生类传入一个消息,

        再调用non_virtual版本来显示。

     

     

     

    */

}


//#10   operator= 返回一个reference to *this

{

   /*

        关于赋值,c++中可以写成连锁形式:

        int x,y,z;

        x = y = z = 15;

        为了实现这种连锁赋值,赋值操作符必须返回一个reference指向操作符的左侧实参。

                                                                        */

   class Widget

    {

    public:

        Widget&operator=(const Widget& rhs)

        {

            ...

           return *this;

        }

    };

}


//#11   operator=中处理自我赋值

{

    //看下面的函数

    Widget&

    Widget::operator=(const Widget& rhs)

    {

       delete pb;

        pb =new Bitmap(*rhs.pb);

       return *this;

    }

    //这样如果是自我赋值,那就先deletepb,最后pb就指向一个已经删除的对象

    //如果让operator=具备异常安全性 往往自动获得自我赋值安全。

    Widget& Widget::operator=(const Widget& rhs)

    {

        Bitmap* pOrig = pb;

        pb =new Bitmap(*rhs.pb);

       delete pOrig;

       return *this;

    }

    //这么做会有效率问题:如果是自我赋值,那就多做了一次new以及delete;但是考虑到自我赋值的几率

    //并不建议在开头加上if判断来判断是否是自己。而且用了if语句,效率会明显下降

    //还有种方法是使用swap保证异常安全性

    Widget& Widget::operator=(const Widget& rhs)

    {

        Widget temp(rhs);

        swap(temp);

       return *this;

    }

    

}


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

{

   /*

        1:当你自己实现operator=操作时,如果你忘记了一个成员变量的复制,编译器不会警告你

        2:当你写自己的operator=或者copy构造函数时应该记得:

            1>复制所有的自己的成员变量

            2>调用所有base classes内的适当的copying函数。

        3:如果发现copy构造函数和copy assignment操作符有相近的代码,消除重复代码的做法是

        建立一个init成员函数,供两者调用。(但是考虑到前面的条目,构造函数直接初始化效率会很高,所以

        如果相近的代码只是赋值的话,还是多动手的好)

     

    */

    PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)

    :Customer(rhs), priority(rhs.priority)

    {

        ...

    }

    

    PriorityCustomer&

    PriorityCustomer::operator=(const PriorityCustomer& rhs)

    {

        ...;

        Customer::operator=(rhs);

        prioriy = rhs.priority;

       return *this;

    }

}












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值