10.3利用父类

10.3利用父类


编写派生类时,需要知道父类和派生类之间的交互方式。创建顺序、构造函数链和类型转换都是潜在的 bug来源。

1.父类构造函数

对象并不是突然建立起来的,创建对象时必须同时创建父类和包含于其中的对象。C++定义了如下的创建顺序:

  • (1)如果某个类具有基类,则执行基类的默认构造函数。除非在 ctor-initializer 中调用了基类构造函数,此时调用这个构造函数而不是默认构造函数。
  • (2)类的非静态数据成员按照声明的顺序创建。
  • (3)执行该类的构造函数。

可递归使用这些规则。如果类有祖父类,祖父类就在父类之前初始化.

C++将自动调用父类的默认构造函数(如果存在的话)。如果父类的默认构造函数不存在,或者存在默认构造函数但希望使用其他构造函数,可在构造函数初始化器(constructor initializer)中像初始化数据成员那样链接(chain)构造函.

class Something
{
  public:
  	Something() {cout << "2";}
};

class Base
{
  public:
  	Base() {cout << "1";}
};

class Derived : public Base
{
  public:
  	Derived() {cout << "3";}
  private:
  	Something m_dataMember;
};

int main()
{
  Derived myDerived;
}

虚方法的行为在构造函数中是不同的、如果派生类重写了基类中的虚方法、从基类构造函数中调用虚方法,就会调用虚方法的基类实现而不是派生类中的重写版本。

2.父类的析构函数

由于析构函数没有参数,因此始终可自动调用父类的析构函数。析构函数的调用顺序刚好与构造函数相反∶

  • (1)调用类的析构函数。
  • (2)销毁类的数据成员,销毁顺序与创建的顺序相反。
  • (3)如果有父类,调用父类的析构函数。

也可递归使用这些规则。链的最底层成员总是第一个被销毁。

3.使用父类方法

在派生类中重写方法时,将有效地替换原始方法。然而,方法的父类版本仍然存在,仍然可以使用这些方法。

4.向上转型和向下转型

如果用派生类对基类的指针或引用赋值,则不会产生截断:

Base& myBase {myDerived};// No slicing

这是通过基类使用派生类的正确途径,也称为向上转型(upcasting)。这也是让方法和函数使用类的引用而不是直接使用类对象的原因。通过使用引用,派生类在传递时没有发生截断。

向下转型有时是必需的,在可控环境中可充分利用这种转换。然而,如果打算进行向下转型,应该使用 dynamic_cast(),以使用对象内建的类型信息,拒绝没有意义的类型转换。这种内建信息通常驻留在虚表中,这意味着dynamic_cast()只能用于具有虚表的对象,即至少有一个虚编号的对象。如果针对某个指针的dynamic_cast()失败,这个指针的值就是 nullptr,而不是指向某个无意义的数据。如果针对对象引用的dynamic_cast()失败,将抛出 std::bad_cast 异常。本章的最后一节将会详细讨论类型转换。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值