继承与多态

继承

访问权限

基类的保护成员可以在派生类的成员函数中被访问,派生类的成员函数只能访问所作用的那个对象(即this指针指向的对象)的基类保护成员,不能访问其他基类对象的基类保护成员。
$$
\begin{array}{|l|l|l|l|}
\hline \text { 类成员/继承方式 } & \text { public继承 } & \text { protected继承 } & \text { private继承 } \
\hline \begin{array}{l}
\text { 基类的public成员 }
\end{array} & \text { 派生类的public成员 } & \text { 派生类的protected成员 } & \text { 派生类的private成员 } \
\hline \begin{array}{l}
\text { 基类的protected成员 }
\end{array} & \text { 派生类的protected成员 } & \text { 派生类的protected成员 } & \text { 派生类的private成员 } \
\hline \begin{array}{l}
\text { 基类的private成员 }
\end{array} & \begin{array}{l}
\text { 不可见,只能通过基类接口访问 }
\end{array} & \begin{array}{l}
\text { 不可见,只能通过基类接口访问 }
\end{array} & \begin{array}{l}
\text { 不可见,只能通过基类接口访问 }
\end{array} \
\hline
\end{array}
$$
基类private成员在派生类中无论以什么方式继承都是不可见的。如果基类成员不想在类外直接访问,但需要在派生类中能访问,就定义为protected。可见,保护成员限定符protected是因为继承才出现的。class默认的继承方式是private,struct默认的继承方式是private。

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。

基类定义了static静态成员,则整个继承体系里只有一个这样的成员。无论派生出多少个子类,都有一个static成员实例。

兼容性规则

1.子类对象可以赋值给父类对象
2.父类对象不能赋值给子类对象
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
//Student的_num和Person的_num构成隐藏关系,可以看出这样的代码虽然能跑,但是非常容易混淆
class Person
{
protected:
string _name = "小李子"; //姓名
int _num = 111; //身份证号
};

class Student :public Person
{
public:
void Print(){
cout << "姓名: " << _name << endl;
cout << "身份证: " << Person::_num << endl;
cout << "学号: " << _num << endl;
}
protected:
int _num = 999; //学号
};

void Test()
{
Student s1;
s1.Print();
}

默认函数

在这里插入图片描述

如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用

from (8条消息) C++中的继承_studyhardi的博客-CSDN博客_c++继承

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
75
76
77
78
79
80
81
#include <iostream>
#include <string>
#include <stdlib.h>

using namespace std;
class Person
{
public:
Person(const char* name = "Romeo")
:_name(name){
cout << "Person()" << endl;
}

Person(const Person& p)
:_name(p._name){
cout << "Person(const Person& p)" << endl;
}

Person& operator=(const Person& p){
cout << "Person& operator=(const Person& p)" << endl;
if (this != &p){
_name = p._name;
}
return *this;
}

~Person(){
cout << "~Person()" << endl;
}
protected:
string _name; //姓名
};

class Student :public Person
{
public:
Student(const char* name, int num)
:Person(name) //调用父类的构造函数完成从父类继承来的成员的初始化
, _num(num)
{
cout << "Student()" << endl;
}

Student(const Student& s)
:Person(s) //调用父类的拷贝构造函数,其中也为“切片”操作,因为父类的拷贝构造函数的参数为引用
, _num(s._num)
{
cout << "Student(const Student& s)" << endl;
}

Student& operator=(const Student& s){
cout << "Student& operator=(const Student& s)" << endl;
if (this != &s){
Person::operator=(s); //调用基类的
_num = s._num;
}
return *this;
}

~Student(){
//此处不需要显示调用父类的析构函数,编译器会自动调用
cout << "~Student()" << endl;
}
protected:
int _num; //学号
};

void Test()
{
Student s1("jack", 18);
Student s2(s1);
Student s3("rose", 17);
s1 = s3;
}

int main()
{
Test();
system("pause");
return 0;
}

多态

C++提供多态的目的是:可以通过基类指针对所有派生类(包括直接派生和间接派生)的成员变量和成员函数进行“全方位”的访问,尤其是成员函数。如果没有多态,我们只能访问成员变量。

  • Copyrights © 2018-2022 Haojia Zhu
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信