继承关系综述

  1. 继承方式

    1. 有三种方式继承 public 继承、protected 继承、private 继承。
    2. 三种继承方式不会改变直接派生类对基类中定义的成员的访问控制权限:

      • 直接派生类内部总能访问基类的 publicprotected 成员。
      • 间接派生类对基类成员的访问就要取决于中间派生类的继承方式。
    3. public 不改变基类定义的成员的访问权限。

      • 基类定义的 publicprotected 成员在派生类中不变。

      • 外界可以访问基类的 public 成员。

    4. protected 继承基类定义的成员的访问权限 >= protected 。

      • 即基类中定义的 public 成员变成在直接派生类中变成 protected 成员。
      • 外部无法访问基类的成员。
      • 间接派生类内部可以访问这个成员。
    5. private 继承基类中定义的成员的访问权限 >= private 。
      • 即基类定义的 publicprotected 成员在派生类变成 private 成员。
      • 外界不能访问基类的成员。
      • 间接派生类内部不可以访问这个成员。
  2. 虚函数与抽象类

    1. 虚函数是带有virtual关键字声明的成员函数。
    2. 纯虚函数 是指带有virtual关键字,并且后面还有=0的函数,纯虚函数是一种特殊的虚函数
    3. 纯虚函数的类称为抽象类,抽象类可以有不止一个纯虚函数。
    4. 抽象类不能直接实例化对象,只能作为基类被继承。
    5. 如果一个派生类继承了一个或多个包含纯虚函数的基类,派生类必须定义所有这些纯虚函数才能实例化,否则该派生类本身也会被视为抽象类。
  3. 函数的重载与重写

    • 重写参数列表与基类虚函数必须相同,否则编译报错。

    • 参数列表不同的同名函数,即重载

  4. override 关键字

    1. 可以用override关键字显式声明派生类要重写基类的虚函数
    2. 只能在重写基类虚函数的时候加 override,否则编译报错。
  5. 指针

    1. 不要用派生类指针指向基类指针。
    2. 基类指针指向派生类对象时,只能调用基类中有声明的方法。
    3. 如果调用基类的虚函数,且该虚函数被派生类重写,则调用的是派生类重写的函数

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>

class Base {
public:
virtual void show() {
std::cout << "Base class show function" << std::endl;
}

void nonVirtualShow() {
std::cout << "Base class non-virtual show function" << std::endl;
}

virtual void pureVirtualShow(int) = 0;
};

class Derived : public Base {
public:
// 重写基类虚函数 show(),此处可以加一个 override
// 等价于 void show() override {...}
void show() {
std::cout << "Derived class show function" << std::endl;
}

// 重载 show 函数
void show(int x){
std::cout << "Derived class show(int x) function" << std::endl;
}

void nonVirtualShow(){
std::cout << "Derived class non-virtual show function" << std::endl;
}

// 错误:override 检查基类中没有 virtual void nonVirtual()
// 注意:不能 override 非虚函数
// void nonVirtualShow() override {
// std::cout << "Derived class non-virtual show function" << std::endl;
// }

// 错误:override 检查基类,没有 virtual void show(float)
// 注意:使用了 override 关键字则只能<重写>基类虚函数,不能<重载>
// void show(float) override{
// std::cout << "Derived class show(int x) function" << std::endl;
// }

// 派生类需要定义基类的纯虚函数后才能实例化
// 注释掉这段定义后无法编译
void pureVirtualShow(int a){
std::cout << "Derived class declared pure-virtual show function" << std::endl;
}
};

int main() {

// 基类指针指向派生类,
Base* basePtr = new Derived();

// 基类指针调用虚函数,若派生类重写则调用派生类的定义
basePtr->show(); // 输出: Derived class show function

// 错误:基类指针无法调用基类没有声明的函数
// 虽然派生类重载的show函数能接收一个int参数
// 但是重载不等同于重写,基类指针无法调用派生类的重载函数
// basePtr->show(1);

// 基类指针调用非虚函数,调用的是基类的实现
basePtr->nonVirtualShow(); // 输出: Base class non-virtual show function

// 纯虚函数也是一种虚函数
// 调用的是派生类的实现
basePtr->pureVirtualShow(1);

delete basePtr;
return 0;
}