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

我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的“可能比较准确”的「翻译」。

Chapter 2 构造 / 析构 / 赋值

条款 05:了解C++ 默默编写并调用哪些函数

如果你写下:
class Empty{ };

事实上编译器会帮你补全:
class Empty{
public:
Empty() { }
Empty(const Empty& rhs) { }
~Empty() { }
Empty& operator=(const Empty& rhs) { }
} ;
这些函数只有被需要时才会被创建出来
默认构造函数只是单纯的将来源对象每个non-static成员变量拷贝到目标对象


条款 06: 若不想使用编译器自动生成的函数,就改明确拒绝

将拷贝构造函数和赋值重载函数显式声明为private吧

但有一个小缺陷,就是member函数和友元函数依然可以访问,但是会造成连接错误(linkage error)
编译的话连接器会报错


条款07: 为多态基类声明 virtual析构函数

不作为基类的类不要声明虚析构函数
有继承关系的基类一定加上virtual析构函数(带多态性质的base class)

pure virtual纯虚构函数: virtual ~XXX() = 0;


条款 08: 别让异常逃离析构函数

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


条款 09: 绝不在构造和析构过程中调用virtual 函数

若是有两个有继承关系的类,主类有一个virtual函数,并在构造函数里调用;子类定义了另一个版本的此函数,当在main里构造此子类对象时,实际上还是先调用基类的构造函数,然而基类构造函数调用的virtual
函数版本实际上还是基类的。若此函数会使用子类里的元素,然而之类成员都还未初始化,就会引发错误

当类中有多个构造函数,它们兴许有共同的部分。有一种较为出色的做法是定义一个void类型的init函数,然后将初始化中需要调用的函数放在里面,将init单独放在构造函数里就好了。

综上,在构造和析构期间不要调用虚函数,因为这类调用从不下降至derived class


条款 10: 令 operator= 返回一个 reference to *this

int x,y,z;
x = y = z = 15;
根据右结合律,可以解释为x = (y = (z = 15));
为了实现连锁赋值,赋值操作赋必须返回一个reference指向操作符左侧实参:

class Widget{
public:
    …
    Widget& operator=(const Widget& rhs){
        …
        return *this;
    }
};

此标准适用于所有与赋值相关运算


条款 11:在 operator=中处理自我赋值

类对象的赋值,看下面一种情况:

class Widget{
    …
private:
    Bitmap* pb;
};

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

存在的问题是,如果*this和rhs是同一个对象,delete操作会同时删除两者的bitmap。可以这样操作:

Widget& Widget::operator=(const Widget& rhs)
{
    if(this==&rhs) return *this;  //如果是自我赋值则不做任何事
    delete pb;
    pb = new Bitmap(*rhs.pb);
    return *this;
}

条款 12: 复制对象时勿忘其每一个成分

如果对于拷贝函数,你的复制成员没有写全,编译器是不会报错的,因为这符合逻辑。所以记得将需要拷贝的成员变量都放进copying函数

另外,当手动撰写继承类的copying函数时,一定记得在初始化列表复制其base class的成分.否则在复制构造函数中base class成分会由base class的default构造函数初始化,而copy assignment函数根本不会管base class的成分
可以这样写:(A extends B)
在copy函数中:

A::A(const A& rhs):B(rhs)
{
    ……
}

在copy assignment函数中:

A& A::operator=(const A& rhs)
{
    if(this==&rhs)
        return *this;
    B::operator=(rhs); //对base class成分进行赋值动作
    ……
    return *this;
}

现在很清楚了,当你编写一个copying函数,请确保(1)复制所有local成员变量(2)调用所有base classes内适当的copying函数


OVER

转载于:https://www.cnblogs.com/1Kasshole/p/9092847.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值