Skip to content
On this page

CPP_类的继承


标签:CPP/面向对象  

继承

  • is a 模型(例如,汽车是交通工具)
    • PS:has a --> 类包含类(例如,汽车对象有引擎对象的属性)
    • PS: use a --> 类包含类,使用它的功能(例如,汽车可多次调用引擎的启动方法)
  • 基于已有的类,定义新类
  • 能够提供代码的复用性
  • 多态的必要条件,没有继承就没有多态
  • B 类继承于 A 类
    • A 类称为父类
    • B 类称为子类或者派生类

格式

cpp
class Child: 继承方式 Parent {}

继承方式

  • public, protected, private
  • 作用:将父类中的不同访问权限的成员,设置继承到子类中的的不同访问标准

invert

  • 继承方式其实就是父类的成员在子类的最高访问权限
  • 默认的继承方式是 private

构造函数

  • 默认会调用父类的无参构造函数
  • 可在初始化列表调用父类的有参构造函数:
cpp
Stu(String n, int p, int m, double s): Person(n,p,m), score(s);
                                       ^^^^^^^^^^^^^^
  • 子类会包含父类的包括私有在内的所有成员,其实是特殊的 has a 关系,在内存中,父类的成员在前

invert

  • 可以通过子类对象来声明一个父类指针或引用 Parent *p = &child

函数隐藏

  • 当子类的函数名称(不是签名)和父类一致的时候,不会报错,这种现象称作函数隐藏
  • 子类对象调用的是子类自己扩展的成员,如果想要使用父类成员,需要在名字前加上父类作用域限定符

特殊成员函数

构造函数

  • 构造函数不会被继承
  • 需要在子类构造函数中调用父类构造函数,若无则默认调用无参构造
  • 父类有有参但无无参构造,则必须显式调用父类构造函数,否则报错
  • 先构造父类再构造子类,

析构函数

  • 不会继承
  • 无需显式调用
  • 先析构子类再析构父类

拷贝构造函数

  • 不会继承
  • 需要显式调用父类拷贝构造函数,默认调用无参构造函数
  • 也设计深浅拷贝问题
cpp
Stu &operator =(const Stu &other) {
  if(this != &other) {
    this->score = other.score;
    Person::operator =(other);
  }
  return *this;
}

多重继承

  • C++ 支持多重继承,可以成员可继承自多个父类
  • 成员重名需要作用域限定符
  • 构造顺序与继承顺序有关,与调用构造函数顺序无关
  • MultipleInheritance.cpp

虚继承

  1. 菱形继承问题,也叫钻石继承,一个公共基类派生出多个中间子类,再由其中 N 个中间子类共同派生出一个汇聚子类
  2. 此时,汇聚子类中,由于不同路线继承关系,会保留多份公共基类继承的成员,造成数据冗余,访问不方便
txt
-----------------------  
   A      ---> 公共基类
 /   \
B     C   ---> 中间子类
 \   /
   D      ---> 汇聚子类
-----------------------
  • 为了解决这个问题,需要使用 virtual 继承
  • 在继承方式前加关键字 virtual
  • 当进行虚继承时,由于汇聚子类保留的一份数据,编译器不知道选取哪一个,直接由公共基类构造(上图的 A)
  • DiamondInheritance.cpp

Last updated: