继承:
- 继承(Inheritance)可以理解为一个类从另一个类获取成员变量和成员函数的过程。例如类 B 继承于类 A,那么 B 就拥有 A 的成员变量和成员函数。
- 派生(Derive)和继承是一个概念,只是站的角度不同。继承是子女接收父亲的产业,派生是父亲把产业传承给儿子。
- 所以被继承的类称为父类或基类,继承的类称为子类或派生类。“子类”和“父类”通常放在一起称呼,“基类”和“派生类”通常放在一起称呼。
- 派生类除了拥有基类的成员,还可以定义自己的新成员,以增强类的功能。以下是两种典型的使用继承的场景:
- 当你创建的新类与现有的类相似,只是多出若干成员变量或成员函数时,可以使用继承,这样不但会减少代码量,而且新类会拥有基类的所有功能。
- 当你需要创建多个类,它们拥有很多相似的成员变量或成员函数时,也可以使用继承。可以将这些类的共同成员提取出来,定义为基类,然后从基类继承,既可以节省代码,也方便后续修改成员。
继承方式:
1 | class 派生类名:[继承方式] 基类名{ |
继承方式限定了基类成员在派生类中的访问权限,包括 public(公有的)、 private(私有的)和 protected(受保护的)。此项是可选项,如果不写, 默认为 private(成员变量和成员函数默认也是 private)。
public 继承方式
- 基类中所有 public 成员在派生类中为 public 属性;
- 基类中所有 protected 成员在派生类中为 protected 属性;基类中所有 private 成员在派生类中不能使用。
protected 继承方式
- 基类中的所有 public 成员在派生类中为 protected 属性;基类中的所有 protected 成员在派生类中为 protected 属性;基类中}的所有 private 成员在派生类中不能使用。
private 继承方式
- 基类中的所有 public 成员在派生类中均为 private 属性;基类中的所有 protected 成员在派生类中均为 private 属性;基类中的所有 private 成员在派生类中不能使用。
总结:
1) 私有成员不能继承
2) public 继承,成员权限不变
3) 其他方式继承,成员类型变成此权限
4) 如果不加继承方式会默认为私有继承


继承中构造和析构顺序:
子类对象在实例化时会首先调用父类的构造函数,父类构造函数执行完毕后,才会调用子类的构造函数
当父类构造函数有参数时,需要在子类初始化列表(参数列表)中显示调用父类构造函数
析构函数调用顺序和构造函数相反

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
using namespace std;
class Base
{
public:
Base()
{
cout<<"Base构造函数!"<<endl;
}
~Base()
{
cout<<"Base析构函数!"<<endl;
}
};
class Son:public Base
{
public:
Son()
{
cout<<"Son构造函数!"<<endl;
}
~Son()
{
cout<<"Son析构函数!"<<endl;
}
};
void test01()
{
//创建一个子类对象会同时创建一个父类对象 比如构造函数,自己不写,系统也会默认写上
//继承中的构造和析构顺序如下:
//先构造父类,再构造子类,析构的顺序与构造的顺序相反
Son s1;
}
int main()
{
test01();
system("pause");
return 0;
}
继承时属性与方法重名 :
当子类成员和父类成员同名时,子类依然从父类继承同名成员
如果子类有成员和父类同名,子类访问其成员默认访问子类的成员(本作用域,就近原则)
在子类通过作用域::进行同名成员区分(在派生类中使用基类的同名成员,显示使用类名限定符)
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
using namespace std;
class Base
{
public:
Base()
{
m_A=100;
}
void func()
{
cout<<"Base - func()调用"<<endl;
}
void func(int a)
{
cout<<"Son - func()调用"<<endl;
}
int m_A;
};
class Son:public Base
{
public:
Son()
{
m_A=200;
}
void func()
{
cout<<"Son - func()调用"<<endl;
}
int m_A;
};
//同名成员属性处理方式
void test01()
{
Son s1;
cout<<s1.m_A<<endl;//Son 下的 m_A 输出200
cout<<s1.Base::m_A<<endl;//通过子类对象 访问父类中同名成员,需要加作用域
}
//同名成员函数处理方式
void test02()
{
Son s2;
s2.func();//直接调用 调用的是子类中的同名成员函数
s2.Base::func();//添加作用域 现在调用的是Base下的func()函数
//如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数
//如果想访问到父类中被隐藏的同名成员函数,需要加作用域
//s.func(100);访问不到 必须加作用域
s2.Base::func(100);
}
int main()
{
test01();
test02();
system("pause");
return 0;
}
多继承:
C++允许一个类继承多个类
语法:class 子类:继承方式 父类1,继承方式 父类2…..
多继承可能会引发父类中有同名成员出现,需要加作用域区分
C++实际开发中不建议用多继承
1
2
3class D: public A, private B, protected C{
//类 D 新增加的成员
}
D 是多继承形式的派生类,它以公有的方式继承 A 类,以私有的方式继承 B 类,以保护的方式继承 C 类。 D 根据不同的继承方式获取 A、 B、 C 中的成员,确定它们在派生类中的访问权限。