10.6有趣而晦涩的继承问题

10.6有趣而晦涩的继承问题

1.修改重写方法的返回类型

在C++中,如果原始的返回类型是某个类的指针或引用,重写的方法可将返回类型改为派生类的指针或引用。这种类型称为协变返回类型(covariant return types)。如果基类和派生类处于平行层次结构(parallel bierarchy)中,使用这个特性可以带来便利。平行层次结构是指,一个类层次结构与另一个类层次结构没有相交,但是存在联系。

注: 不能使用智能指针, 类模板会创建两个实例.

2.派生类中添加虚基类方法的重载

可以向派生类中添加虚基类方法的新重载。也就是说,可以使用新原型在派生类中添加虚方法的重载,但继续继承基类版本。该技术使用 using 声明将方法的基类定义显式包含在派生类中。

class Base
{
  public:
  	virtual void someMethod();
};

class Derived : public Base
{
  public:
  	using Base::someMethod();
  	virtual void someMethod(int i);
};

3.继承的构造函数

允许在派生类中继承基类的构造函数, 方法同上节。

3.1隐藏继承的构造函数

定义的构造函数可与从 Base 类继承的构造函数有相同的参数列表。与所有的重写一样,此时Derived类的构造函数的优先级高于继承的构造函数。

使用 using 子句从基类继承构造函数有一些限制。

  • 当从基类继承构造函数时,会继承除默认构造函数外的其他全部构造函数,不能只是继承基类构造函数的一个子集。
  • 当继承构造函数时,无论 using 声明位于哪个访问规范下,都将使用与基类中相同的访问规范来继承。

3.2继承的构造函数和多重继承

第二个限制与多重继承有关。如果一个基类的某个构造函数与另一个基类的构造函数具有相同的参数列表,就不可能从基类继承构造函数,因为那样会导致歧义。为解决这个问题,Derived 类必须显式地定义冲突的构造函数。

3.3数据成员的初始化

使用类内初始化器

4.重写方法时的特殊情况

4.1静态基类方法

在C++中,不能重写静态方法。

首先,方法不可能既是静态的又是虚的。出于这个原因,试图重写一个静态方法并不能得到预期的结果。如果派牛类中存在的静态方法与基类中的静态方法同名,实际上这是两个独立的方法。

静态方法属于定义它的类,而不属于特定的对象。当类中的方法调用静态方法时,所调用的版本是通过正常的名称解析来决定的。当使用对象调用时,对象实际上并不涉及调用、只是用来判断编译期的类型。

4.2重载基类方法

当指定名称和一组参数以重写某个方法时,编译器隐式地隐藏基类中同名方法的所有其他实例。

如果只想改变一个方法,可以使用using 关键字避免重载该方法的所有版本。

为了避免歧义bug,应该重写所有版本的重载方法。

4.3基类的private方法

重写 private 方法当然没有问题。记住方法的访问说明符会判断谁可以调用这些方法。派生类无法调用父类的private 方法,并不意味着无法重写这个方法。

4.4基类方法具有默认参数

派生类与基类可以具有不同的默认参数,但使用的参数取决于声明的变量类型,而不是底层的对象.

4.5基类方法具有不同的访问级别

可以采用两种方法修改方法的访问级别——可以加强限制,也可放宽限制

为加强某个方法(或数据成员)的限制,有两种方法。一种方法是修改整个基类的访问说明符,另一种方法是在派生类中重新定义访问限制,

5.派生类中的复制构造函数和赋值运算符

如果在派生类中指定了复制构造函数,就需要显式地链接到父类的复制构造函数,下面的代码演示了这一内容。如果不这么做,将使用默认构造函数(不是复制构造函数!)初始化对象的父类部分。

6.运行期类型工具

7.非public继承

8.虚基类

虚基类(virtual base class)在C++中用于解决多继承时的二义性问题,并且是实现混合继承或多重继承时的一种重要机制。

当派生类从多个基类派生,而这些基类又共享一个或多个相同的基类时,就会出现所谓的“菱形继承”(diamond inheritance)问题。如果一个类同时从两个或多个路径继承自同一个基类,而这个基类的某些成员在多条路径上被多次继承,那么派生类中就会存在多个这样的成员的副本,从而导致不明确的引用。

为了解决这个问题,C++引入了虚基类的概念。通过将基类声明为虚基类,可以确保在派生类中只继承一份该基类的成员,而不是每个路径上都继承一份。这样,就消除了由于多路径继承而导致的二义性。

使用虚基类的语法是在派生列表中使用关键字virtual来修饰对应的基类。例如:

class A { /* ... */ };

class B : virtual public A { /* ... */ };

class C : virtual public A { /* ... */ };

class D : public B, public C { /* ... */ };

在这个例子中,类D继承了类B和类C,而类B和类C都继承自类A。通过将类A声明为虚基类,类D中只会继承一份类A的成员,从而避免了二义性。

总结来说,虚基类的作用是解决多继承中的二义性问题,确保在派生类中只继承一份共享基类的成员,从而实现了更清晰的继承关系和避免潜在的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值