C++ primer 学习记录:面对对象编程之构造函数和复制控制

构造函数和复制控制

构造函数和复制控制成员不能继承,每个类定义自己的构造函数和复制控制成员。像任何类一样,如果类不定义自己的默认构造函数和复制控制成员,就将使用合成版本。

基类构造函数和复制控制

本身不是派生类的基类,其构造函数和复制控制基本上不受继承影响。构造函数看起来像已经见过的许多构造函数一样:
Item_base(const std::string &book = "",
double sales_price = 0.0):
isbn(book), price(sales_price) { }
继承对基类构造函数的唯一影响是,在确定提供哪些构造函数时,必须考虑一类新用户。像任意其他成员一样,构造函数可以为protected 或 private,某些类需要只希望派生类使用的特殊构造函数,这样的构造函数应定义为protected。

派生类构造函数

派生类的构造函数受继承关系的影响,每个派生类构造函数除了初始化自己的数据成员之外,还要初始化基类。

合成的派生类默认构造函数

派生类的合成默认构造函数与非派生的构造函数只有一点不同:除了初始化派生类的数据成员之外,它还初始化派生类对象的基类部分。基类部分由基类的默认构造函数初始化。

定义默认构造函数

因为Bulk_item 具有内置类型成员,所以应定义自己的默认构造函数:
class Bulk_item : public Item_base {
public:
Bulk_item(): min_qty(0), discount(0.0) { }
// as before
};
这个构造函数使用构造函数初始化列表初始化min_qty 和 discount 成员,该构造函数还隐式调用 Item_base 的默认构造函数初始化对象的基类部分。
运行这个构造函数的效果是,首先使用Item_base 的默认构造函数初始化 Item_base 部分,那个构造函数将 isbn 置为空串并将 price 置为 0。Item_base 的构造函数执行完毕后,再初始化Bulk_item 部分的成员并执行构造函数的函数体(函数体为空)。

向基类构造函数传递实参

除了默认构造函数之外,Item_base 类还使用户能够初始化 isbn 和 price 成员,我们希望支持同样 Bulk_item 对象的初始化,事实上,我们希望用户能够指定整个Bulk_item 的值,包括折扣率和数量。
派生类构造函数的初始化列表只能初始化派生类的成员,不能直接初始化继承成员。相反派生类构造函数通过将基类包含在构造函数初始化列表中来间接初始化继承成员。
class Bulk_item : public Item_base {
public:
Bulk_item(const std::string& book, double sales_price,
std::size_t qty = 0, double disc_rate = 0.0):
Item_base(book, sales_price),
min_qty(qty), discount(disc_rate) { }
// as before
};
这个构造函数使用有两个形参Item_base 构造函数初始化基类子对象,它将自己的 book 和 sales_price 实参传递给该构造函数。这个构造函数可以这样使用:
// arguments are the isbn, price, minimum quantity, and discount
Bulk_item bulk("0-201-82470-1", 50, 5, .19);
要建立bulk,首先运行Item_base 构造函数,该构造函数使用从 Bulk_item 构造函数初始化列表传来的实参初始化 isbn 和 price。Item_base 构造函数执行完毕之后,再初始化Bulk_item 的成员。最后,运行 Bulk_item 构造函数的(空)函数体。
构造函数初始化列表为类的基类和成员提供初始值,它并不指定初始化的执行次序。首先初始化基类,然后根据声明次序初始化派生类的成员。

只能初始化直接基类

一个类只能初始化自己的直接基类。直接就是在派生列表中指定的类。如果类C 从类 B 派生,类 B 从类 A 派生,则 B 是 C 的直接基类。虽然每个 C 类对象包含一个 A 类部
分,但C 的构造函数不能直接初始化 A 部分。相反,需要类 C 初始化类 B,而类B 的构造函数再初始化类 A。这一限制的原因是,类B 的作者已经指定了怎样构造和初始化
B 类型的对象。像类 B 的任何用户一样,类 C 的作者无权改变这个规约。

复制控制和继承

像任意其他类一样,派生类也可以使用合成复制控制成员。合成操作对对象的基类部分连同派生部分的成员一起进行复制、赋值或撤销,使用基类的复制构造函数、赋值操作符或析构函数对基类部分进行复制、赋值或撤销。
类是否需要定义复制控制成员完全取决于类自身的直接成员。基类可以定义自己的复制控制而派生类使用合成版本,反之亦然。
只包含类类型或内置类型数据成员、不含指针的类一般可以使用合成操作,复制、赋值或撤销这样的成员不需要特殊控制。具有指针成员的类一般需要定义自己的复制控制来管理这些成员。

定义派生类复制构造函数

如果派生类显式定义自己的复制构造函数或赋值操作符,则该定义将完全覆盖默认定义。被继承类的复制构造函数和赋值操作符负责对基类成分以及类自己的成员进行复制或赋值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值