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++的更多相关文章

  1. Multiple inheritance in Go

    原文:http://golangtutorials.blogspot.com/2011/06/multiple-inheritance-in-go.html --------------------- ...

  2. 面向对象程序设计-C++ Inheritance & Multiple inheritance & RTTI【第十三次上课笔记】

    Sadly, 这节课带过去的笔记本没电了 T^T 导致没有一行 Code, Sorry 笔记如下: Shape * p1; //使用指针创建对象的方法 p = new Circle (2.0); Sh ...

  3. 条款40:明智而审慎地使用多重继承(use multiple inheritance judiciously)

    NOTE: 1.多重继承比单一继承复杂.它可能导致新的歧义性,以及对virtual继承的需要. 2.virtual 继承会增加大小 速度 初始化(及赋值)复杂度等等成本.如果virtual base ...

  4. Memory Layout for Multiple and Virtual Inheritance

    Memory Layout for Multiple and Virtual Inheritance(By Edsko de Vries, January 2006)Warning. This art ...

  5. JavaScript Patterns 6.2 Expected Outcome When Using Classical Inheritance

    // the parent constructor function Parent(name) { this.name = name || 'Adam'; } // adding functional ...

  6. [置顶] c++类的继承(inheritance)

    在C++中,所谓"继承"就是在一个已存在的类的基础上建立一个新的类.已存在的类(例如"马")称为"基类(base class )"或&quo ...

  7. Classical Inheritance in JavaScript

    JavaScript is a class-free, object-oriented language, and as such, it uses prototypal inheritance in ...

  8. (转) Friendship and inheritance

    原地址: http://www.cplusplus.com/doc/tutorial/inheritance/ Friend functions In principle, private and p ...

  9. <Effective C++>读书摘要--Inheritance and Object-Oriented Design<二>

    <Item 36> Never redefine an inherited non-virtual function 1.如下代码通过不同指针调用同一个对象的同一个函数会产生不同的行为Th ...

随机推荐

  1. 云知声 Atlas 超算平台: 基于 Fluid + Alluxio 的计算加速实践

    Fluid 是云原生基金会 CNCF 下的云原生数据编排和加速项目,由南京大学.阿里云及 Alluxio 社区联合发起并开源.本文主要介绍云知声 Atlas 超算平台基于 Fluid + Alluxi ...

  2. lumen、laravel问题汇总

    框架报500 1.chmod 777 -R storage 将日志目录权限设置下. 2.修改fastcgi,将代码目录包含进去. fastcgi_param PHP_ADMIN_VALUE " ...

  3. vue强制组件重新渲染

    有时候,依赖 Vue 响应方式来更新数据是不够的,相反,我们需要手动重新渲染组件来更新数据.或者,我们可能只想抛开当前的DOM,重新开始.那么,如何让Vue以正确的方式重新呈现组件呢? 强制 Vue ...

  4. 2021CISCN 华南赛区WEB wp

    CISCN 华南区域赛 太菜了 我躺平了 easy_seri <?php error_reporting(0); highlight_file(__FILE__); class Test{ pu ...

  5. 【JAVA】笔记(2)---面向过程与面向对象;类,对象;实例变量,引用;构造方法;

    面向过程与面向对象: 1.面向过程思想的典型栗子是C语言,C语言实现一个程序的流程是:在主函数中一步一步地罗列代码(定义子函数来罗列也是一样的道理),以此来实现我们想要的效果: 2.面向对象思想的典型 ...

  6. Jetpack架构组件学习(1)——LifeCycle的使用

    原文地址:Jetpack架构组件学习(1)--LifeCycle的使用 | Stars-One的杂货小窝 要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 最近 ...

  7. 【GitHub】本地代码上传

    本地代码上传GitHub 2019-11-18  20:03:45  by冲冲 1.注册GitHub https://github.com/ 2.安装Git工具 https://git-for-win ...

  8. java 后台通过IO流把文件传到前端并下载

    我的业务需求是两个不同的web程序放在不同的服务器上,web程序A要访问到web程序B上传上来的文件,所以用到了这一个IO读取文件的接口 JAVA代码(排版有点问题  已经尽力补救了(:3_ヽ)_) ...

  9. Python之浏览器的前进或后退

    import webbrowserwebbrowser.back() 后退webbrowser.forward() 前进

  10. 浅谈Java和JavaScript中变量和数据类型的区别

    对于一门编程语言的学习,如果第一步是安装环境,那么第二步一定是学习这门语言的基本规则,变量和数据类型则首当其冲 JavaScipt作为一个蹭Java热度而命名的语言,在很多方面和Java也有一定的相似 ...