C++ 面向对象-继承

本文最后更新于:2022年4月22日 上午

继承是面向对象中的第二大特性

继承的基本使用

在 类后面 通过 public xxx 来实现继承

class Animal {
public:
  string name;
};

class Dog : public Animal { };

void three_test1() {
  Dog d;
  d.name = "哈士奇";

  cout << d.name << endl;
}

// ...

three_test1();

输出

哈士奇

继承的方式

  • public XXX

  • protected XXX

  • private XXX

以上三个都不能够在子类中访问 private 成员,

通过以上不同的关键字进行继承,会将父类 public/protected 修饰的成员继承到子类对应的 public/protected/private

继承的对象模型

在 开发人员命令提示工具 cd 到对应的目录,然后输入 cl /d1 reportSingleClassLayoutPerson "xxxxx.cpp"

cl 是英文,d1 中的1是数字1

继承时构造和析构的顺序

  • 构造函数 先调用父类的构造,再调用子类的构造

  • 析构函数 先调用子类的析构,再调用父类的析构

继承时同名属性的处理(子类重写父类属性/方法)

如果子类重写了父类的属性或者方法,需要通过作用域来访问,如 xxx.YYY::zzz,其中 xxx是子类,YYY是父类,zzz是父类中的成员

class Father {

public:
  static string name;
  void sayName() {
    cout << "Father sayName" << endl;
  }

  void sayName(string name) {
    cout << "Father sayName:" << name << endl;
  }
};

string Father::name = "Father";

class Son : public Father {

public:

  static string name;

  // 子类重写 sayName
  void sayName() {
    cout << "Son sayName" << endl;
  }
};

string Son::name = "Son";

void three_test2() {
  Son s;
  
  // 调用子类的 sayName;
  s.sayName();

  // 调用父类的 sayName; 需要加上作用域
  s.Father::sayName();

  // 子类不能够直接调用到父类重载的方法
  //s.sayName("小明")

  // 需要通过作用域才能够访问到父类的方法
  s.Father::sayName("小明");

  // 静态属性同理
  // 通过对象去访问
  // 访问子类的静态属性
  cout << s.name << endl;
  // 访问父类的静态属性
  cout << s.Father::name << endl;

  // 通过 类去访问

  cout << Son::name << endl;
  cout << Son::Father::name << endl;

}

菱形继承

菱形继承的场景在于 一个 父类,有个 name 属性,它下面有两个子类, 此时又有一个类同时继承这两个子类,这就会出现重复属性(name)了

virtual 是表示虚继承,可以通过查看对象的模型进行查看

class Animal4 {
public:
  string name;
};

// 虚继承
class Sheep : virtual public Animal4 { };  // 羊
class Camel : virtual public Animal4 { };  // 驼

// 羊驼
class Alpaca : public Sheep, public Camel {};

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。