在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度。现在将跟着视频做的笔记进行整理。本篇博客是整理C++知识点的第十五篇博客。
本篇博客介绍了C++的继承。
本系列博客所有C++代码都在Visual Studio 2022环境下编译运行。程序为64位。
目录
有些时候,类之间具有一定的关系。一些类拥有其他类的共性,和自己的特性。
可以利用继承,减少重复的代码。继承的语法是:
class A: 继承方式 B
继承方式分为public protected和private
A类称为子类,或派生类。B类称为父类,或基类。
子类的成员既有父类的成员,也有自己的成员。从父类继承的成员体现了共性,子类自己的成员体现了个性。
- #include
- using namespace std;
- class same {
- public:
- void show(void) {
- cout << "It is object oriented programming" << endl;
- }
- void test(void) {
- cout << "Study this is very hard" << endl;
- }
-
- void thing(void) {
- cout << "It has encapsulation,inheritance and polymorphism" << endl;
- }
- };
- class Java :public same
- {
- public:
- void inform(void) {
- cout << "This is Java" << endl;
- }
- };
-
- class CPP :public same
- {
- public:
- void inform(void) {
- cout << "This is C++" << endl;
- }
- };
-
- int main(void)
- {
- Java learnjava;
- learnjava.inform();
- learnjava.show();
- learnjava.test();
- learnjava.thing();
-
- CPP learncpp;
- learncpp.inform();
- learncpp.show();
- learncpp.test();
- learncpp.thing();
- return 0;
- }
same类有三个成员函数,show成员函数输出It is object oriented programming,test成员函数输出Study this is very hard,thing成员函数输出It has encapsulation,inheritance and polymorphism。Java类以public权限继承了same类,该类自己的成员函数inform输出This is Java。CPP类以public权限继承了same类,该类自己的成员函数inform输出This is C++。
main函数定义了Java类对象learnjava和C++类对象learncpp,分别调用其成员函数,可见子类可以有父类的成员。程序的输出是:
This is Java
It is object oriented programming
Study this is very hard
It has encapsulation,inheritance and polymorphism
This is C++
It is object oriented programming
Study this is very hard
It has encapsulation,inheritance and polymorphism
如果类A以public的继承方式继承了类X,那么X的public权限成员在A中仍然为public,X的protected权限成员在A中仍然为protected,X的private权限成员在A中不可访问。
如果类B以protected的继承方式继承了类X,那么X的public权限成员和protected权限成员在A中均为protected,X的private权限成员在A中不可访问。
如果类C以private的继承方式继承了类X,那么X的public权限成员和protected权限成员在A中均为private,X的private权限在A中不可访问。
- #include
- using namespace std;
- class base {
- public:
- int A;
- protected:
- int B;
- private:
- int C;
- };
- class son1 :public base
- {
- public:
- void func(void) {
- A = 10;
- B = 10;
- }
- void show(void) {
- cout << "A = " << A << endl;
- cout << "B = " << B << endl;
- }
- };
- class son2 :protected base
- {
- public:
- void func(void) {
- A = 12;
- B = 12;
- }
- void show(void) {
- cout << "A = " << A << endl;
- cout << "B = " << B << endl;
- }
- };
- class son3 :private base
- {
- public:
- void func(void) {
- A = 11;
- B = 11;
- }
- void show(void) {
- cout << "A = " << A << endl;
- cout << "B = " << B << endl;
- }
- };
-
- int main(void)
- {
- son1 s1;
- s1.func();
- s1.A = 15;
- s1.show();
-
- son2 s2;
- s2.func();
- s2.show();
- son3 s3;
- s3.func();
- s3.show();
- return 0;
- }
base类的成员变量A B C分别为public protected private。子类son1 son2 son3分别以public protected private的方式继承了base类,并且都有func成员函数进行赋值,show成员函数用于输出。main函数中创建了son1 son2 son3类的对象并调用func函数show函数。
程序的输出是:
A = 15
B = 10
A = 12
B = 12
A = 11
B = 11
父类的所有非静态成员属性都会被子类继承,即使子类无法访问,也是被继承了。
- #include
- using namespace std;
- class base {
- public:
- int A;
- protected:
- int B;
- private:
- int C;
- };
-
- class son :public base
- {
- public:
- int D;
- void func(void) {
- A = 5;
- B = 10;
- D = 0;
- }
- };
-
- int main(void)
- {
- son s;
- cout << sizeof(s) << endl;
- return 0;
- }
base类有public权限的成员属性A,protected权限的成员属性B,private权限的成员属性C,共三个成员属性。类son以public继承了base,自身还有成员属性D和成员函数func。
main函数创建了son类对象s,并输出其大小。程序的输出是:16
即使son类不可访问C,但是依然继承了C。
创建子类对象也会调用父类的构造函数。先构造父类再构造子类,析构相反。
- #include
- using namespace std;
- class father {
- public:
- father() {
- cout << "A" << endl;
- }
- ~father() {
- cout << "Z" << endl;
- }
- };
-
- class son :public father
- {
- public:
- son() {
- cout << "a" << endl;
- }
- ~son() {
- cout << "z" << endl;
- }
- };
- int main(void)
- {
- son s;
- return 0;
- }
father类的构造函数输出A,析构函数输出Z。father类的子类son的构造函数输出a,析构函数输出z。main函数创建了一个son类的对象s。程序的输出是:
A
a
z
Z
当子类与父类的成员属性同名时,通过子类对象,访问子类的同名成员直接访问即可,访问父类的同名成员则需要加作用域。
如果子类出现和父类同名的成员函数,则子类的成员函数隐藏父类的同名成员函数,访问父类的同名函数需要加作用域。
- #include
- using namespace std;
- class father {
- public:
- void func() {
- cout << "This is father's func" << endl;
- }
- void func(int num) {
- cout << "This is father's func" << endl;
- cout << "And there is a number = " << num << endl;
- }
-
- int number = 5;
- };
- class son :public father
- {
- public:
- int number = 10;
- void func() {
- cout << "This is son's func" << endl;
- }
- };
-
- int main(void)
- {
- son s;
- cout << "Son's number is " << s.number << endl;
- cout << "Father's number is " << s.father::number << endl;
- s.func();
- s.father::func();
- s.father::func(100);
- return 0;
- }
father类有成员变量number,起始值为5,此外重载了两个func成员函数,一个没有参数,输出This is father's func,另一个接收一个int类型变量,并会输出其值。son类以public的权限继承了father类,内有成员变量number,起始值为10,还有成员函数func输出This is son's func。这样父类和子类出现了成员属性同名和成员变量同名。
main函数创建了son类对象s,并访问其本身和父类的同名成员函数以及同名成员变量。
程序的输出是:
Son's number is 10
Father's number is 5
This is son's func
This is father's func
This is father's func
And there is a number = 100
如果继承时出现了同名静态成员,那么通过子类对象,依然是访问子类的直接访问,访问父类的需要加作用域。
- #include
- using namespace std;
- class father {
- public:
- static int number;
- static void func(void) {
- cout << "This is father's func" << endl;
- }
- };
-
- class son :public father
- {
- public:
- static int number;
- static void func(void) {
- cout << "This is son's func" << endl;
- }
- };
-
- int father::number = 10;
- int son::number = 15;
-
- int main(void)
- {
- cout << "son's number = " << son::number << endl;
- cout << "father's number = " << son::father::number << endl;
- son s;
- cout << "son's number = " << s.number << endl;
- cout << "father's number = " << s.father::number << endl;
-
- s.func();
- s.father::func();
- son::func();
- son::father::func();
- return 0;
- }
父类father和子类son都有静态成员变量number(都类外赋值),和静态成员函数func(输出不同语句)。main函数通过子类类名和子类对象访问了同名静态成员。程序的输出是:
son's number = 15
father's number = 10
son's number = 15
father's number = 10
This is son's func
This is father's func
This is son's func
This is father's func
C++允许一个类继承多个类,语法是:
class 子类:继承方式 父类1 继承方式 父类2...{...}
多继承可能导致父类中出现同名成员,需要用作用域区分。实际开发不建议使用多继承。
- #include
- using namespace std;
- class father1
- {
- public:
- int A;
- int C;
- };
- class father2
- {
- public:
- int B;
- int C;
- };
-
- class son :public father1, public father2
- {
- public:
- int D;
- };
- int main(void)
- {
- son s;
- s.A = 10;
- s.B = 20;
- s.father1::C = 15;
- s.father2::C = 16;
- s.D = 12;
- cout << "A in father1 is " << s.A << endl;
- cout << "B in father2 is " << s.B << endl;
- cout << "C in father1 is " << s.father1::C << endl;
- cout << "C in father2 is " << s.father2::C << endl;
- cout << "D in son is " << s.D << endl;
- return 0;
- }
类father1有成员变量A和C,类father2有成员变量B和C,类son同时继承father1和father2,自身还有成员变量D。main函数创建了son类对象s,并访问其成员。由于son的两个父类都有成员变量C,因此需要用作用域区分。程序的输出是:
A in father1 is 10
B in father2 is 20
C in father1 is 15
C in father2 is 16
D in son is 12
如果类B和类C都继承自类A,而类D同时继承类B和类C。那么A的成员变量在B和C中可能有两个值,导致与事实的冲突。
virtual关键字表示虚继承,被虚继承的类是虚基类,这样数据只有一份。
- #include
- using namespace std;
- class first {
- public:
- int number;
- };
- class second1 : virtual public first {
- };
- class second2 :virtual public first {
- };
- class third : public second1, public second2 {
- };
- int main(void)
- {
- third three;
- three.second1::number = 20;
- cout << three.second1::number << endl;
- cout << three.number << endl;
- three.second2::number = 25;
- cout << three.second2::number << endl;
- cout << three.number << endl;
- return 0;
- }
first类有成员变量number,second1和second2对first类进行虚继承,而third类同时继承second1和second2。
main函数创建了third的类对象three,并通过两个不同父类作用域修改number为不同值,这时运行结果:
20
20
25
25
虚继承保证了这种继承的在子类数据的唯一性。