欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++中的多重继承(一)

程序员文章站 2022-07-09 21:26:49
1,C++ 中是否允许一个类继承自多个父类? 1,可以; 2,这种情况就是多重继承; 3,多重继承的表象就是一个类有多个父类; 4,这是 C++ 非常特别的一个特性,在其他的程序设计语言中比如 C#、Java、Object Pascal 中都只支持单重继承; 2,C++ 支持编写多重继承的代码: 1 ......

1,c++ 中是否允许一个类继承自多个父类?

    1,可以;

    2,这种情况就是多重继承;

    3,多重继承的表象就是一个类有多个父类;

    4,这是 c++ 非常特别的一个特性,在其他的程序设计语言中比如 c#、java、object pascal 中都只支持单重继承;

   

2,c++ 支持编写多重继承的代码:

    1,一个子类可以拥有多个父类;

    2,子类拥有所有父类的成员变量;

    3,子类继承所有父类的成员函数;

    4,子类对象可以当作任意父类对象使用;

   

3,多重继承的语法规则:

    1,代码示例:

1 class derived : public basea, public baseb, public basec
2 {
3     // ...
4 };

    2,多重继承的本质与单继承相同;

   

4,多重继承问题一编程实验:

  1 #include <iostream>
  2 #include <string>
  3 
  4 using namespace std;
  5 
  6 class basea
  7 {
  8     int ma;
  9     
 10 public:
 11     basea(int a)
 12     {
 13         ma = a;
 14     }
 15     
 16     int geta()
 17     {
 18         return ma;
 19     }
 20 };
 21 
 22 class baseb
 23 {
 24     int mb;
 25     
 26 public:
 27     baseb(int b)
 28     {
 29         mb = b;
 30     }
 31     
 32     int getb()
 33     {
 34         return mb;
 35     }
 36 };
 37 
 38 class derived : public basea, public baseb
 39 {
 40     int mc;
 41     
 42 public:
 43     derived(int a, int b, int c) : basea(a), baseb(b)  // 初始化列表中同时调用父类的构造函数;
 44     {
 45         mc = c;
 46     }
 47     
 48     int getc()
 49     {
 50         return mc;
 51     }
 52     
 53     void print()
 54     {
 55         cout << "ma = " << geta() << ", "
 56              << "mb = " << getb() << ", "
 57              << "mc = " << mc << endl;
 58     }
 59 };
 60 
 61 int main()
 62 {
 63     cout << "sizeof(derived) = " << sizeof(derived) << endl;    // 12
 64     
 65     derived d(1, 2, 3);
 66     
 67     d.print();
 68     
 69     cout << "d.geta() = " << d.geta() << endl;  // 1
 70     cout << "d.getb() = " << d.getb() << endl;  // 2
 71     cout << "d.getc() = " << d.getc() << endl;  // 3
 72     
 73     cout << endl;
 74     
 75     basea* pa = &d;
 76     baseb* pb = &d;
 77     
 78     cout << "pa->geta() = " << pa->geta() << endl;  // 1
 79     cout << "pb->getb() = " << pb->getb() << endl;  // 2
 80     
 81     cout << endl;
 82     
 83     void* paa = pa;
 84     void* pbb = pb;
 85     
 86     
 87     if( paa == pbb )
 88     {
 89         cout << "pointer to the same object!" << endl; 
 90     }
 91     else
 92     {
 93         cout << "error" << endl;  // 打印 error;
 94     }
 95     
 96     cout << "pa = " << pa << endl;  // 0xbfe7e304
 97     cout << "pb = " << pb << endl;  // 0xbfe7e308
 98     cout << "paa = " << paa << endl;  // 0xbfe7e304
 99     cout << "pbb = " << pbb << endl;   // 0xbf7e308
100     
101     return 0;
102 }

   

5,通过多重继承得到的对象可能拥有“不同地址”:

    1,解决方案:无;

    2,多重继承成员变量排布:

 C++中的多重继承(一)

       1,指向同一个对象的不同位置;

       2,不方便开发了,因为我们一般比较这两个指针是否相同来判断是否指向同一个对象;

       3,这里两个地址值不同依然可能指向同一个对象,情况变得非常复杂;

   

6,多重继承可能产生冗余的成员:

C++中的多重继承(一) 

    1,doctor 这个类有两个 m_name,两个 m_age;

   

7,多重继承问题二编程实验:

    1,描述 本文6 中类图:

 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 : virtual public people
24 {
25 public:
26     teacher(string name, int age) : people(name, age)
27     {
28     }
29 };
30 
31 class student : virtual 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 + 1), student(name, age), people(name, age)
43     {      // 如果在这里没有调用 people(name, age),编译器会在这一样显示如下错误:
44        // error: no matching function for call to 'people::people()'
45         // note: candidates are: people::people(std::string, int)  这是在父类构造的一行;
46     }    // note: people::people(const people&) ,这个编译器提供,在类最开始那一行;
47 };
48 
49 int main()
50 {
51     doctor d("delphi", 33);
52     
53     d.print();  // 未有虚继承时,编译器显示:error: request for member 'print' is  ambiguous
54           //  error: candidates are: void people::print()
55                 //  error:                 void people::print()
56     /* 未有虚继承时,可以这样分作用域分辨符来继承 */
57     d.teacher::print();  // name = delphi, age = 33;
58     d.student::print();  // name = delphi, age = 33;
59     
60     return 0;
61 }

   

8,多重继承关系出现闭合时将产生数据冗余的问题:

    1,解决方案:虚继承;

    2,代码示例:

1 class people {};
2 class teacher : virtual public people {};
3 class student : virtual public people {};
4 class doctor : public teacher, public student {};

      

9,多重继承的问题二:

    1,虚继承能够解决数据冗余问题;

   2,中间层父类不再关心顶层父类的初始化;

       1,规则不清晰;

       2,当今的软件产品,动则几十万行代码,业务逻辑已经很复杂了,我们希望编程语言越简单越好,不希望几套标准,这样的话,只会造成生成效率的低下和致命的 bug;

       3,工程中可能是很多层继承,这样找的很麻烦,可以几班解决;

   3,最终子类必须直接调用顶层父类的构造函数;

  

10,问题:

    1,当架构设计需要继承时,无法确定使用直接继承还是虚继承;

       1,开发者感觉增加了开发时间;

       2,架构设计时,无法知道开发者是否会多重继承;

       3,都做成虚继承的时候,多重继承加虚继承太过复杂,影响效率和移植性(不同编译器可能有不同实现方式);

       4,多重继承只适合学术研究,工程一般不使用;

   

11,小结:

    1,c++ 支持多重继承的编程方式;

       1,除了 c++ 支持多重继承,基本上其它语言并不支持;

    2,多重继承容易带来问题:

       1,可能出现“同一个对象的地址不同”的情况;

       2,虚继承可以解决数据冗余的问题;

       3,虚继承使得架构设计可能出现问题;