C++继承深度解析

2022/6/15 5:20:12

本文主要是介绍C++继承深度解析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一.继承的概念

继承是C++中代码复用的重要手段。通过继承,可以获得父类的所有功能,并且可以在子类中重写已有功能,或者添加新功能。

  1 #include <iostream>
  2 #include <string>
  3  
  4 using namespace std;
  5  
  6 class Memory
  7 {
  8 public:
  9     Memory()
 10     {
 11         cout << "Memory()" << endl;
 12     }
 13     ~Memory()
 14     {
 15         cout << "~Memory()" << endl;
 16     }
 17 };
 18  
 19 class Disk
 20 {
 21 public:
 22     Disk()
 23     {
 24         cout << "Disk()" << endl;
 25     }
 26     ~Disk()
 27     {
 28         cout << "~Disk()" << endl;
 29     }   
 30 };
 31  
 32 class CPU
 33 {
 34 public:
 35     CPU()
 36     {
 37         cout << "CPU()" << endl;
 38     }
 39     ~CPU()
 40     {
 41         cout << "~CPU()" << endl;
 42     }    
 43 };
 44  
 45 class MainBoard
 46 {
 47 public:
 48     MainBoard()
 49     {
 50         cout << "MainBoard()" << endl;
 51     }
 52     ~MainBoard()
 53     {
 54         cout << "~MainBoard()" << endl;
 55     }    
 56 };
 57  
 58 class Computer
 59 {
 60     Memory mMem;
 61     Disk mDisk;
 62     CPU mCPU;
 63     MainBoard mMainBoard;
 64 public:
 65     Computer()
 66     {
 67         cout << "Computer()" << endl;
 68     }
 69     void power()
 70     {
 71         cout << "power()" << endl;
 72     }
 73     void reset()
 74     {
 75         cout << "reset()" << endl;
 76     }
 77     ~Computer()
 78     {
 79         cout << "~Computer()" << endl;
 80     }
 81 };
 82  
 83 class HPBook : public Computer
 84 {
 85     string mOS;
 86 public:
 87     HPBook()
 88     {
 89         mOS = "Windows 8";
 90     }
 91     void install(string os)
 92     {
 93         mOS = os;
 94     }
 95     void OS()
 96     {
 97         cout << mOS << endl;
 98     }
 99 };
100  
101 class MacBook : public Computer
102 {
103 public:
104     void OS()
105     {
106         cout << "Mac OS" << endl;
107     }
108 };
109  
110 int main()
111 {   
112     HPBook hp;
113     
114     hp.power();  //子类调用power()
115     hp.install("Ubuntu 16.04 LTS");
116     hp.OS();
117     
118     cout << endl;
119     
120     MacBook mac;
121     
122     mac.OS();
123     
124     return 0;
125 }

结果:

 1 //HPBook类实例化过程
 2 Memory()      //先父母的成员变量
 3 Disk()
 4 CPU()
 5 MainBoard()
 6 Computer()    //父母的自身
 7 power()
 8 Ubuntu 16.04 LTS
 9 //MacBook类实例化过程
10 Memory()
11 Disk()
12 CPU()
13 MainBoard()
14 Computer()
15 Mac OS
16 ~Computer()
17 ~MainBoard()
18 ~CPU()
19 ~Disk()
20 ~Memory()
21 ~Computer()
22 ~MainBoard()
23 ~CPU()
24 ~Disk()
25 ~Memory()    

继承构造调用关系:先是调用父类的成员变量,然后再调用父类自身,再调用子类,析构的顺序则与构造的顺序相反。

二.继承中的访问级别

子类不能直接访问父类的私有成员private。

 1 #include <iostream>
 2 #include <string>
 3  
 4 using namespace std;
 5  
 6 class Parent
 7 {
 8 private:
 9     int mv;
10 public:
11     Parent()
12     {
13         mv = 100;
14     }
15     
16     int value()
17     {
18         return mv;
19     }
20 };
21  
22 class Child : public Parent
23 {
24 public:
25     int addValue(int v)
26     {
27         mv = mv + v;    // ???? 如何访问父类的非公有成员
28     }
29 };
30  
31 int main()
32 {   
33     return 0;
34 }

结果:编译错误

protected修饰的成员可以被子类及外界直接访问。

 1 #include <iostream>
 2 #include <string>
 3  
 4 using namespace std;
 5  
 6 class Parent
 7 {
 8 protected:
 9     int mv;
10 public:
11     Parent()
12     {
13         mv = 100;
14     }
15     
16     int value()
17     {
18         return mv;
19     }
20 };
21  
22 class Child : public Parent
23 {
24 public:
25     int addValue(int v)
26     {
27         mv = mv + v;    
28     }
29 };
30  
31 int main()
32 {   
33     Parent p;
34     
35     cout << "p.mv = " << p.value() << endl;  //100
36     
37     Child c;
38     
39     cout << "c.mv = " << c.value() << endl;    //100
40     
41     c.addValue(50);
42     
43     cout << "c.mv = " << c.value() << endl;    //150
44     
45     return 0;
46 }

用public修饰的的父类可以被子类及外界访问。用protected修饰的父类可以被子类访问,不能被外界访问。用private修饰的父类只能被父类的成员函数访问。

三.继承中子类与父类的同名成员变量,成员函数

通过作用域分辨符(::)访问父类中的同名成员

1 Child c;
2 c.mi = 100;           //子类中的mi
3 c.Parent::mi = 1000;  //父类中的mi
 1 #include <iostream>
 2 #include <string>
 3  
 4 using namespace std;
 5  
 6 class Parent
 7 {
 8 public:
 9     int mi;
10     
11     Parent()
12     {
13         cout << "Parent() : " << "&mi = " << &mi << endl;  
14     }   //确认成员变量地址,定位类Parent
15 };
16  
17 class Child : public Parent
18 {
19 public:
20     int mi;
21     
22     Child()
23     {
24         cout << "Child() : " << "&mi = " << &mi << endl;
25     }   //确认成员变量地址,定位类Child
26 };
27  
28 int main()
29 {
30     Child c;
31     
32     c.mi = 100;    
33     
34     c.Parent::mi = 1000;      //作用域分辨符,和命名空间有点像
35     
36     cout << "&c.mi = " << &c.mi << endl;  //查看是子类的
37     cout << "c.mi = " << c.mi << endl;
38     
39     cout << "&c.Parent::mi = " << &c.Parent::mi << endl;    //查看的是父类的
40     cout << "c.Parent::mi = " << c.Parent::mi << endl;
41     
42     return 0;
43 }

结果:

1 Parent() : &mi = 0xbfb99188
2 Child() : &mi = 0xbfb918c
3 &c.mi = 0xbfb9918c   //证明调用的子类mi
4 c.mi = 100     //打印子类中的mi
5 &c.Parent::mi = 0xbfb99188    //证明调用的子类继承自父类的mi
6 c.Parent::mi = 1000    //打印父类中的mi

当子类和父类有同名成员时,父类成员被子类覆盖,但是它依然存在子类中。

父类和子类之间的重载:

 1 #include <iostream>
 2 #include <string>
 3  
 4 using namespace std;
 5  
 6 class Parent
 7 {
 8 public:
 9     int mi;
10     
11     void add(int v)  //重载关系  
12     {
13         mi += v;
14     }
15     
16     void add(int a, int b)    //重载关系
17     {
18         mi += (a + b);
19     }
20 };
21  
22 class Child : public Parent
23 {
24 public:
25     int mi;
26     
27     void add(int x, int y, int z)
28     {
29         mi += (x + y + z);
30     }
31 };
32  
33 int main()
34 {
35     Child c;
36     
37     c.mi = 100;    //访问子类的mi
38     
39     c.Parent::mi = 1000;    //访问子类继承父类的mi
40     
41     cout << "c.mi = " << c.mi << endl;
42     
43     cout << "c.Parent::mi = " << c.Parent::mi << endl;
44     
45     c.Parent::add(1);        //解决方案
46     c.Parent::add(2, 3);
47     c.add(4, 5, 6);
48  
49     cout << "c.mi = " << c.mi << endl;
50     
51     cout << "c.Parent::mi = " << c.Parent::mi << endl;
52     
53     return 0;
54 }

结果:

1 c.mi = 100
2 c.Parent::mi = 1000    
3 c.mi = 115             //调用子类add(4, 5, 6)
4 c.Parent::mi = 1006    //调用父类add(1)和add(2,3)    

子类无法重载父类中的成员函数(作用域不同),使用作用域分辨符c.Parent::add访问父类中的同名函数。

子类和父类中的函数不能构成重载关系,子类可以定义父类中完全相同的成员函数。

四.多重继承可能产生冗余的成员

菱形继承:

 1 #include <iostream>
 2 #include <string>
 3  
 4 using namespace std;
 5  
 6 class People
 7 {
 8     string m_name;
 9     int m_age;
10 public:
11     People(string name, int age)
12     {
13         m_name = name;
14         m_age = age;
15     }
16     void print()
17     {
18         cout << "Name = " << m_name << ", "
19              << "Age = " << m_age << endl;
20     }
21 };
22  
23 class Teacher : public People
24 {
25 public:
26     Teacher(string name, int age) : People(name, age) //调用父类构造函数
27     {
28     }
29 };
30  
31 class Student : public People
32 {
33 public:
34     Student(string name, int age) : People(name, age)  //调用父类构造函数
35     {
36     }
37 };
38  
39 class Doctor : public Teacher, public Student
40 {
41 public:
42     Doctor(string name, int age) : Teacher(name, age), Student(name, age)
43     {
44     }
45 };
46  
47 int main()
48 {
49     Doctor d("Delphi", 33);
50     
51     d.print();
52     
53     return 0;
54 }

结果:编译出错

 



这篇关于C++继承深度解析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程