Multiple Inheritance in C++
Multiple Inheritance is a feature of C++ where a class can inherit from more than one classes.
The constructors of inherited classes are called in the same order in which they are inherited. For example, in the following program, B’s constructor is called before A’s constructor.
1 #include<iostream>
2 using namespace std;
3
4 class A
5 {
6 public:
7 A()
8 {
9 cout << "A's constructor called" << endl;
10 }
11 };
12
13 class B
14 {
15 public:
16 B()
17 {
18 cout << "B's constructor called" << endl;
19 }
20 };
21
22 class C: public B, public A // Note the order
23 {
24 public:
25 C()
26 {
27 cout << "C's constructor called" << endl;
28 }
29 };
30
31 int main()
32 {
33 C c;
34 return 0;
35 }
Output:
B's constructor called
A's constructor called
C's constructor called
The destructors are called in reverse order of constructors.
The diamond problem
The diamond problem occurs when two superclasses of a class have a common base class.
For example, in the following diagram, the TA class gets two copies of all attributes of Person class, this causes ambiguities.
For example, consider the following program.
1 #include<iostream>
2 using namespace std;
3 class Person
4 {
5 // Data members of person
6 public:
7 Person(int x)
8 {
9 cout << "Person::Person(int ) called" << endl;
10 }
11 };
12
13 class Faculty : public Person
14 {
15 // data members of Faculty
16 public:
17 Faculty(int x):Person(x)
18 {
19 cout<<"Faculty::Faculty(int ) called"<< endl;
20 }
21 };
22
23 class Student : public Person
24 {
25 // data members of Student
26 public:
27 Student(int x):Person(x)
28 {
29 cout<<"Student::Student(int ) called"<< endl;
30 }
31 };
32
33 class TA : public Faculty, public Student
34 {
35 public:
36 TA(int x):Student(x), Faculty(x)
37 {
38 cout<<"TA::TA(int ) called"<< endl;
39 }
40 };
41
42 int main()
43 {
44 TA ta1(30);
45 }
Output:
Person::Person(int ) called
Faculty::Faculty(int ) called
Person::Person(int ) called
Student::Student(int ) called
TA::TA(int ) called
In the above program, constructor of ‘Person’ is called two times. Destructor of ‘Person’ will also be called two times when object ‘ta1′ is destructed. So object 'ta1' has two copies of all members of ‘Person’, this causes ambiguities(歧义). The solution to this problem is ‘virtual’ keyword. We make the classes ‘Faculty’ and ‘Student’ as virtual base classes to avoid two copies of ‘Person’ in ‘TA’ class.
For example, consider the following program.
1 #include<iostream>
2 using namespace std;
3 class Person {
4 public:
5 Person(int x)
6 {
7 cout << "Person::Person(int ) called" << endl;
8 }
9 Person()
10 {
11 cout << "Person::Person() called" << endl;
12 }
13 };
14
15 class Faculty : virtual public Person
16 {
17 public:
18 Faculty(int x):Person(x)
19 {
20 cout<<"Faculty::Faculty(int ) called"<< endl;
21 }
22 };
23
24 class Student : virtual public Person
25 {
26 public:
27 Student(int x):Person(x)
28 {
29 cout<<"Student::Student(int ) called"<< endl;
30 }
31 };
32
33 class TA : public Faculty, public Student
34 {
35 public:
36 TA(int x):Student(x), Faculty(x)
37 {
38 cout<<"TA::TA(int ) called"<< endl;
39 }
40 };
41
42 int main()
43 {
44 TA ta1(30);
45 }
Output:
Person::Person() called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called
In the above program, constructor of ‘Person’ is called once. One important thing to note in the above output is, the default constructor of ‘Person’ is called. When we use ‘virtual’ keyword, the default constructor of grandparent class is called by default even if the parent classes explicitly call parameterized constructor.
How to call the parameterized constructor of the ‘Person’ class? The constructor has to be called in ‘TA’ class.
For example, see the following program.
1 #include<iostream>
2 using namespace std;
3 class Person {
4 public:
5 Person(int x)
6 {
7 cout << "Person::Person(int ) called" << endl;
8 }
9 Person()
10 {
11 cout << "Person::Person() called" << endl;
12 }
13 };
14
15 class Faculty : virtual public Person
16 {
17 public:
18 Faculty(int x):Person(x)
19 {
20 cout<<"Faculty::Faculty(int ) called"<< endl;
21 }
22 };
23
24 class Student : virtual public Person
25 {
26 public:
27 Student(int x):Person(x)
28 {
29 cout<<"Student::Student(int ) called"<< endl;
30 }
31 };
32
33 class TA : public Faculty, public Student
34 {
35 public:
36 TA(int x):Student(x), Faculty(x), Person(x) //the difference
37 {
38 cout<<"TA::TA(int ) called"<< endl;
39 }
40 };
41
42 int main()
43 {
44 TA ta1(30);
45 }
Output:
Person::Person(int ) called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called
In general, it is not allowed to call the grandparent’s constructor directly, it has to be called through parent class. It is allowed only when ‘virtual’ keyword is used.
As an exercise, predict the output of following programs.
Question 1
1 #include<iostream>
2 using namespace std;
3
4 class A
5 {
6 int x;
7 public:
8 void setX(int i)
9 {
10 x = i;
11 }
12 void print()
13 {
14 cout << x;
15 }
16 };
17
18 class B: public A
19 {
20 public:
21 B()
22 {
23 setX(10);
24 }
25 };
26
27 class C: public A
28 {
29 public:
30 C()
31 {
32 setX(20);
33 }
34 };
35
36 class D: public B, public C
37 {43 };
44
45 int main()
46 {
47 D d;
48 d.print();
49 return 0;
50 }
编译错误: 'D::print' is ambiguous
Question 2
1 #include<iostream>
2 using namespace std;
3
4 class A
5 {
6 int x;
7 public:
8 void setX(int i)
9 {
10 x = i;
11 }
12 void print()
13 {
14 cout << x;
15 }
16 };
17
18 class B: virtual public A
19 {
20 public:
21 B()
22 {
23 setX(10);
24 }
25 };
26
27 class C: virtual public A
28 {
29 public:
30 C()
31 {
32 setX(20);
33 }
34 };
35
36 class D: public B, public C
37 {
38
39 };
40
41 int main()
42 {
43 D d;
44 d.print();
45 return 0;
46 }
Output: 20
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
转载请注明:http://www.cnblogs.com/iloveyouforever/
2013-11-26 20:11:35
Multiple Inheritance in C++的更多相关文章
- Multiple inheritance in Go
原文:http://golangtutorials.blogspot.com/2011/06/multiple-inheritance-in-go.html --------------------- ...
- 面向对象程序设计-C++ Inheritance & Multiple inheritance & RTTI【第十三次上课笔记】
Sadly, 这节课带过去的笔记本没电了 T^T 导致没有一行 Code, Sorry 笔记如下: Shape * p1; //使用指针创建对象的方法 p = new Circle (2.0); Sh ...
- 条款40:明智而审慎地使用多重继承(use multiple inheritance judiciously)
NOTE: 1.多重继承比单一继承复杂.它可能导致新的歧义性,以及对virtual继承的需要. 2.virtual 继承会增加大小 速度 初始化(及赋值)复杂度等等成本.如果virtual base ...
- Memory Layout for Multiple and Virtual Inheritance
Memory Layout for Multiple and Virtual Inheritance(By Edsko de Vries, January 2006)Warning. This art ...
- JavaScript Patterns 6.2 Expected Outcome When Using Classical Inheritance
// the parent constructor function Parent(name) { this.name = name || 'Adam'; } // adding functional ...
- [置顶] c++类的继承(inheritance)
在C++中,所谓"继承"就是在一个已存在的类的基础上建立一个新的类.已存在的类(例如"马")称为"基类(base class )"或&quo ...
- Classical Inheritance in JavaScript
JavaScript is a class-free, object-oriented language, and as such, it uses prototypal inheritance in ...
- (转) Friendship and inheritance
原地址: http://www.cplusplus.com/doc/tutorial/inheritance/ Friend functions In principle, private and p ...
- <Effective C++>读书摘要--Inheritance and Object-Oriented Design<二>
<Item 36> Never redefine an inherited non-virtual function 1.如下代码通过不同指针调用同一个对象的同一个函数会产生不同的行为Th ...
随机推荐
- MarkdownPad2弹窗显示HTML Rendering Error(HTML 渲染错误)的解决办法
MarkdownPad2弹窗显示HTML Rendering Error(HTML 渲染错误)的解决办法 我在打开.md文件的时候,出现以下错误: 解决方式:下载Awesomium SDK并安装,重启 ...
- coding game, 边打游戏边学编程,是一种怎么样的体验?
前言 hello,大家好,我是bigsai,好久不见,甚是想念! 在日常生活中,很多人喜欢玩游戏,因为游戏中有着对抗博弈.控制的喜悦,用灵魂指法完成一波靓丽的操作. 但实际上,你的按键都是对应代码中一 ...
- 1. 处理静态资源 2. controller如何接受请求得参数 3. 如何把controller得数据保存到view. 4. 在controller如何完成重定向到指定路径 5. controller返回json数据
1. 1. 处理静态资源2. controller如何接受请求得参数3. 如何把controller得数据保存到view.4. 在controller如何完成重定向到指定路径5. controller ...
- MySQL基础语句(MySQL内置函数 )
MySQL 字符串函数 函数 描述 实例 ASCII(s) 返回字符串 s 的第一个字符的 ASCII 码. 返回 CustomerName 字段第一个字母的 ASCII 码: SELECT ASCI ...
- C#疑问
在Microsoft.NET里面int=Int32Int64=long但是在其他.NET环境下面可能不是这样的.C#是一门计算机编程语言,是经过标准化,也就是说其他的人也可以根据它的语法去实现它的编译 ...
- [nfls338]基本字典子串
1.前置知识 以下数字未特殊说明,取值范围均与$N$取交 以下字符串未特殊说明,下标均从1开始,且均为非空串,复杂度中的$n$指字符串长度 周期和border 对于非空集合$S$,定义$\ ...
- [gym101981F]Frank
在本题中,每一步是独立的,因此即可以看作从$s$移动到$t$的期望步数(对于每一对$s$和$t$都求出答案) 令$f_{i,j}$表示当$s=i$且$t=j$时的答案,则有$f_{i,j}=\begi ...
- [atARC098F]Donation
贪心,一定在最后一次经过某节点时付出$b_{u}$,条件是付出后$W\ge \max(a_{i}-b_{i},0)$(同时也可以仅考虑这个限制,因为$W$在过程中不会增大) 假设"最后一次经 ...
- 【JavaSE】JDK配置
Java开发环境配置 2020-09-10 08:32:20 by冲冲 1. Windows7安装JDK 1.1 下载JDK ① 下载地址:http://www.oracle.com/techne ...
- HTML四种定位-固定定位
固定定位 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset=&q ...