Skip to content

10 继承和派生

派生与成员函数

特性 重载 (Overload) 隐藏 (Hide) 覆盖 (Override)
作用域 同一个类或作用域内 派生类与基类之间 派生类与基类之间
函数名 相同 相同 相同
参数列表 必须不同 可以不同,也可以相同 必须完全相同
virtual 关键字 无关 无关 基类函数必须是 virtual
目的 用同一个函数名处理不同类型/数量的参数 派生类屏蔽基类同名函数 实现运行时多态,改变父类行为
  • 如果想调用基类被隐藏的函数,需要使用 基类名:: 前缀

  • 运算符重载本质上是函数的重载,规则与函数相同,但是编译器总会为派生类自动生成 operator=,这会隐藏基类版本。

改变访问控制

  • 基类中的public或protected成员,因使用protected或private继承访问控制而导致在派生类中的访问方式发生改变,可以使用“访问声明”恢复为原来的访问控制方式

    using 基类名::成员名;
    

  • 通常 using 声明不改变访问权限(比如在命名空间或派生类中引入基类函数时,保持原权限)。但在类作用域内对基类成员使用 using 时,它会根据 using 出现的位置重新设定访问级别。using 声明写在哪个权限区,该成员就变成什么权限。

class Base {
private:
    int val = 10;
public:
    void show() { cout << val << endl; }
};

// 公有继承
class Derive : public Base {
public:
    // using 提升基类私有成员到派生类public权限
    using Base::val;
};

int main() {
    Derive d;
    d.val = 100;   // 外部可访问,权限已改为public
    d.show();
    return 0;
}
  • 屏蔽基类成员:
    • 用 private/protected 继承 整体屏蔽,这是真正彻底屏蔽,外部完全不能访问
    • 在 private/protected 权限区利用 using 降级,仍然可以通过基类::访问。
  • 用于继承对象的重命名:
    • 目的:在派生类中选择更合适的术语命名继承成员。
    • 方法:屏蔽旧函数,在派生类中定义新的函数,该函数调用旧函数。
  • 使用基类构造函数:使用using 基类名::基类名使用基类的各个构造函数。