C++中的多重继承

简介: 🐰多重继承🌸声明多重继承的方法🌸多重继承派生类的构造函数与析构函数🌸多重继承引起的二义性

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

🐰多重继承

🌸声明多重继承的方法

🌸多重继承派生类的构造函数与析构函数

🌸多重继承引起的二义性


🐰多重继承

定义:多重继承是指派生类具有两个或两个以上的直接基类

🌸声明多重继承的方法

多重继承可以看作是单继承的扩展,派生类和每个基类之间的关系可以看作是一个单继承。多重继承派生类的声明格式如下:

1. class 派生类名:(继承方式)基类名1,...,(继承方式)基类名n
2. {
3.     派生类新增的成员
4. }

其中不同的基类可以选择不同的继承方式

🌸多重继承派生类的构造函数与析构函数

多重继承方式,定义派生类构造函数的形式:

1. 派生类名(总参数列表):基类名(参数表1),...,基类名n(参数n),新增的数据成员(参数1),...,新增数据成员(参数n)
2. {
3.     ;
4. }

其中,总参数列表必须包含完成所有基类数据成员初始化所需的参数。

多重继承方式下派生类的构造函数与单继承方式下派生类构造函数相似,但同时负责该派生类所有基类构造函数的调用。构造函数调用的顺序为:先调用所有基类的构造函数,再执行派生类构造函数的函数体。所有基类构造函数的调用顺序将按照它们在继承方式中的声明次序调用,而不是按派生类构造函数参数初始化列表中的书写次序调用。

例如:

1. #include<iostream>
2. using namespace std;
3. class Base1
4. {
5. public:
6. Base1(int BAse1)
7.     {
8.         cout<<"调用了Base1的构造函数"<<endl;
9.         base1=BAse1;
10.     }
11.     ~Base1()
12.     {
13.         cout<<"调用了Base1的析构函数"<<endl;
14.     }
15. protected:
16. int base1;
17. };
18. class Base2
19. {
20. public:
21. Base2(int BAse2)
22.     {
23.         cout<<"调用了Base2的构造函数"<<endl;
24.         base2=BAse2;
25.     }
26.     ~Base2()
27.     {
28.         cout<<"调用了Base2的析构函数"<<endl;
29.     }
30. protected:
31. int base2;
32. };
33. class Base3:public Base1,public Base2
34. {
35. public:
36. Base3(int BAse1,int BAse2,int BAse3):Base1(BAse1),Base2(BAse2)
37.     {
38.         cout<<"调用了Base3的构造函数"<<endl;
39.         base3=BAse3;
40.     }
41.     ~Base3()
42.     {
43.         cout<<"调用了Base3的析构函数"<<endl;
44.     }
45. private:
46. int base3;
47. };
48. int main()
49. {
50. Base3 s1(520,13,14);
51. }
52. 
53. 运行结果:
54. 调用了Base1的构造函数
55. 调用了Base2的构造函数
56. 调用了Base3的构造函数
57. 调用了Base3的析构函数
58. 调用了Base2的析构函数
59. 调用了Base1的析构函数

派生类析构函数的执行,多重继承方式也与单继承方式类似。派生类析构函数的执行顺序,首先执行派生类析构函数的函数体,对派生类新增的数据成员所涉及的额外内存空间清理,然后调用基类的析构函数,对从基类继承来的成员所涉及的额外内存空间进行清理。所有基类的析构函数将按照它们在继承方式中的声明次序的逆序、从右向左调用(与其构造函数执行顺序正好相反)。

🌸多重继承引起的二义性

在多重继承的方式下,派生类继承了多个基类的成员。如果在这多个基类中拥有同名的成员,那么,派生类在继承各个基类的成员之后,当调用该派生类的这些同名成员时,就会出现二义性,编译器无法确定应该选择派生类哪一个成员。

二义性主要分为以下3种类型:

(1)两个基类有同名成员

1. #include<iostream>
2. using namespace std;
3. class Sofa
4. {
5. public:
6. Sofa(string Name):name(Name)
7.     {
8.         cout<<"The is Sofa construction"<<endl;
9.     }
10. void show()
11.     {
12.         cout<<"name="<<name<<endl;
13.     }
14. protected:
15.     string name;
16. };
17. class Bed
18. {
19. public:
20. Bed(string Name):name(Name)
21.     {
22.         cout<<"The is Bed construction"<<endl;
23.     }
24. void show()
25.     {
26.         cout<<"name="<<name<<endl;
27.     }
28. protected:
29.     string name;
30. };
31. class SofaBed:public Sofa,public Bed
32. {
33. public:
34. SofaBed(string Name1,string Name2,string Name3):Sofa(Name1),Bed(Name2),name(Name3)
35.     {
36.         cout<<"The is Sofa construction"<<endl;
37.     }
38. void disshow()
39.     {
40.         cout<<"name="<<name<<endl;//虽然和基类Sofa和Bed的数据成员名一样,但是在派生类中会被重写
41.         cout<<"name="<<Bed::name<<endl;
42.         cout<<"name="<<Sofa::name<<endl;
43.         cout<<"name="<<SofaBed::name<<endl;
44.     }
45. protected:
46.     string name;
47. };
48. int main()
49. {
50. SofaBed s1("沙发","床","沙发床");
51. //    s1.show();//这里会出现二义性,因为无法知道这个show函数是基类Sofa和Bed的那一个的
52.     s1.Sofa::show();
53.     s1.Bed::show();
54.     s1.disshow();
55. }
56. 结果:
57. The is Sofa construction
58. The is Bed construction
59. The is Sofa construction
60. name=沙发
61. name=床
62. name=沙发床
63. name=床
64. name=沙发
65. name=沙发床

s1.show()为了解决这个二义性,我们可以使用类名来限定,如 s1.Sofa::show()s1.Bed::show()

(2)两个基类和派生类三者都有同名函数

1. #include<iostream>
2. using namespace std;
3. class Sofa
4. {
5. public:
6. Sofa(string Name):name(Name)
7.     {
8.         cout<<"The is Sofa construction"<<endl;
9.     }
10. void show()
11.     {
12.         cout<<"name="<<name<<endl;
13.     }
14. protected:
15.     string name;
16. };
17. class Bed
18. {
19. public:
20. Bed(string Name):name(Name)
21.     {
22.         cout<<"The is Bed construction"<<endl;
23.     }
24. void show()
25.     {
26.         cout<<"name="<<name<<endl;
27.     }
28. protected:
29.     string name;
30. };
31. class SofaBed:public Sofa,public Bed
32. {
33. public:
34. SofaBed(string Name1,string Name2,string Name3):Sofa(Name1),Bed(Name2),name(Name3)
35.     {
36.         cout<<"The is Sofa construction"<<endl;
37.     }
38. void show()
39.     {
40.         cout<<"name="<<name<<endl;//虽然和基类Sofa和Bed的数据成员名一样,但是在派生类中会被重写
41.         cout<<"name="<<Bed::name<<endl;
42.         cout<<"name="<<Sofa::name<<endl;
43.         cout<<"name="<<SofaBed::name<<endl;
44.     }
45. protected:
46.     string name;
47. };
48. int main()
49. {
50. SofaBed s1("沙发","床","沙发床");
51.     s1.show();
52. }
53. 结果:
54. The is Sofa construction
55. The is Bed construction
56. The is Sofa construction
57. name=沙发床
58. name=床
59. name=沙发
60. name=沙发床

程序能够正常编译,同时也能正常运行。show()虽然和基类Sofa和Bed的成员函数的声明一样,但是在派生类中会被重写

(3)如果两个基类从一个基类派生的

1. #include<iostream>
2. using namespace std;
3. class Wood
4. {
5. public:
6. Wood()
7.     {
8.         cout<<"The is Wood construction"<<endl;
9.     }
10. void Show()
11.     {
12.         cout<<"name="<<name<<endl;
13.     }
14. protected:
15.     string name="木头";
16. };
17. class Sofa:public Wood
18. {
19. public:
20. Sofa(string Name):name(Name)
21.     {
22.         cout<<"The is Sofa construction"<<endl;
23.     }
24. void show()
25.     {
26.         cout<<"name="<<name<<endl;
27.     }
28. protected:
29.     string name;
30. };
31. class Bed:public Wood
32. {
33. public:
34. Bed(string Name):name(Name)
35.     {
36.         cout<<"The is Bed construction"<<endl;
37.     }
38. void show()
39.     {
40.         cout<<"name="<<name<<endl;
41.     }
42. protected:
43.     string name;
44. };
45. class SofaBed:public Sofa,public Bed
46. {
47. public:
48. SofaBed(string Name1,string Name2,string Name3):Sofa(Name1),Bed(Name2),name(Name3)
49.     {
50.         cout<<"The is Sofa construction"<<endl;
51.     }
52. void disshow()
53.     {
54.         cout<<"name="<<name<<endl;//虽然和基类Sofa和Bed的数据成员名一样,但是在派生类中会被重写
55.         cout<<"name="<<Bed::name<<endl;
56.         cout<<"name="<<Sofa::name<<endl;
57.         cout<<"name="<<SofaBed::name<<endl;
58.     }
59. protected:
60.     string name;
61. };
62. int main()
63. {
64. SofaBed s1("沙发","床","沙发床");
65.     s1.Sofa::Show();
66.     s1.Bed::Show();
67. }
68. 结果:
69. The is Wood construction
70. The is Sofa construction
71. The is Wood construction
72. The is Bed construction
73. The is Sofa construction
74. name=木头
75. name=木头

SafaBed的两个基类Safa和Bed从一个基类Wood派生。虽然在类Safa和Bed中没有定义成员函数Show,但是它们都从Show中继承了成员函数,这样类Safa和Bed中同时存在同名的成员函数Show。如果在main函数中用派生类SofaBed创建一个对象,s1,并调用Show,不能直接用s1.Show()或者s1.Wood::Show()。因为无法判断是从基类Safa和Bed那一个继承的。如果要调用应该这样

s1.Sofa::Show();

s1.Bed::Show();

🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸

 

相关文章
|
6月前
|
C++
C++程序中的多重继承
C++程序中的多重继承
68 1
|
4月前
|
编译器 C++ 开发者
C++一分钟之-多重继承与菱形问题
【7月更文挑战第19天】C++的多重继承允许类从多个基类派生,但引入了菱形问题,即类D通过B和C(都继承自A)双重继承A,可能导致数据冗余和二义性。解决这个问题的关键是**虚继承**,通过`virtual`关键字确保基类A只被继承一次,消除冲突。理解并适当使用虚继承是处理这类问题的关键,有助于保持代码的清晰和正确性。
66 0
|
6月前
|
设计模式 编译器 数据安全/隐私保护
C++ 多级继承与多重继承:代码组织与灵活性的平衡
C++的多级和多重继承允许类从多个基类继承,促进代码重用和组织。优点包括代码效率和灵活性,但复杂性、菱形继承问题(导致命名冲突和歧义)以及对基类修改的脆弱性是潜在缺点。建议使用接口继承或组合来避免菱形继承。访问控制规则遵循公有、私有和受保护继承的原则。在使用这些继承形式时,需谨慎权衡优缺点。
99 1
|
6月前
|
C++
[C++/PTA] 日程安排(多重继承+重载)
[C++/PTA] 日程安排(多重继承+重载)
186 0
|
Java 编译器 PHP
C++的多重继承
派生类都只有一个基类,称为单继承(Single Inheritance)。除此之外,C++也支持多继承(Multiple Inheritance),即一个派生类可以有两个或多个基类。 多继承容易让代码逻辑复杂、思路混乱,一直备受争议,中小型项目中较少使用,后来的 Java、C#、PHP 等干脆取消了多继承。 多继承的语法也很简单,将多个基类用逗号隔开即可。例如已声明了类A、类B和类C,那么可以这样来声明派生类D: class D: public A, private B, protected C{ //类D新增加的成员 } D 是多继承形式的派生类,它以公有的方式继承 A 类,
|
Java 编译器 Android开发
Android C++系列:C++最佳实践4多重继承与虚继承
Java和C++在语法层面比较的时候就不得不提到C++的多继承,我们知道Android是单继承,C++是多继承。在大型项目中不可避免的会用到多继承,本文分析C++多继承的一些特征。
140 0
|
Java C++
C++继承与派生解析(继承、重载/转换运算符、多重继承、多态、虚函数/纯虚函数、抽象类)
C++继承与派生解析(继承、重载/转换运算符、多重继承、多态、虚函数/纯虚函数、抽象类)
196 0
C/C++---Person类、学生类、教师类和研究生类(多重继承)
C/C++---Person类、学生类、教师类和研究生类(多重继承)
900 0
|
C++
C++第13周项目2 - 多重继承教师类和干部类
课程首页地址:http://blog.csdn.net/sxhelijian/article/details/7910565,本周题目链接:http://blog.csdn.net/sxhelijian/article/details/8953304 【项目2】分别定义Teacher(教师)类和Cadre(干部)类,采用多重继承方式由这两个类派生出新类Teacher_Cadre(教师兼干部)
1603 0