学习多重继承和虚继承

多重继承:

  • 非虚函数,两个基类存在满足覆盖条件的函数时,派生类无法调用其中任何一个函数。该条件只有一个要求:重名。无论返回值、参数、const类型如何,只要重名,即满足覆盖条件。

虚继承:

  1. 伴随虚继承衍生出来了虚基类的概念,当一个B虚继承了A时,A就是B的虚基类,虚基类的概念只存在于虚继承关系两个类之间,当此时C正常继承A时,A相对于C就不是虚基类。
  2. 无论虚继承还是虚基类,都与虚函数无关。
  3. 使用虚继承时,两个中间类都必须是虚继承于最基类,否则无论虚函数还是非虚函数,都会产生两份函数。

正常使用方法:

  1. 两个中间类虚继承与最基类,之后最派生类正常继承于两个中间类;
  2. 两个中间类必须保证不同时覆盖某个虚函数或同时覆盖某个非虚函数,否则会造成最派生类调用函数不明确;
  3. 此时,最派生类对象会根据这两个中间类的函数实现情况,去选择应该调用的函数,如(2)中所述,最近基类必须无冲突。
  4. 其实,此时最派生类所继承的是两个中间类的合集,如下图所示:

非虚继承时对象的结构,虚继承对于对象结构的影响:

非虚继承的类图:

非虚继承的实例的数据结构:

虚继承的类图:

虚继承的实例的数据结构:

输出结果分析:

程序代码:

  1 #include <stdlib.h>
  2 
  3 /***
  4 * @author:zanzan101
  5 */
  6 
  7 class A
  8 {
  9 private:
 10     int data1;
 11 public:
 12     A():data1(1){}
 13     void do_something()
 14     {
 15         printf("A\n");
 16     }
 17     virtual void foo()
 18     {
 19         printf("A:foo\n");
 20     }
 21     virtual void func()
 22     {
 23         printf("A:func\n");
 24     }
 25 };
 26 
 27 class B
 28 {
 29 private:
 30     int data2;
 31 public:
 32     B():data2(2){}
 33     virtual void func(){}
 34     void do_something(int)
 35     {
 36         printf("B\n");
 37     }
 38 };
 39 
 40 class C: public A
 41 {
 42 private:
 43     int data31;
 44 public:
 45     C():data31(31), A(){}
 46     virtual void foo()
 47     {
 48         printf("C:foo\n");
 49     }
 50     virtual void to_string()
 51     {
 52         printf("this is a C\n");
 53     }
 54 };
 55 
 56 class D: public A
 57 {
 58 private:
 59     int data32;
 60 public:
 61     D():data32(32), A(){}
 62     virtual void func()
 63     {
 64         printf("D:foo\n");
 65     }    
 66 };
 67 
 68 class E: public C, public D
 69 {
 70 private:
 71     int data33;
 72 public:
 73     E():data33(33), C(), D(){}
 74 };
 75 
 76 class F: public virtual A
 77 {
 78 protected:
 79     int data4;
 80 public:
 81     F(): data4(4){}
 82     void func()
 83     {
 84         printf("F:func\n");
 85     }
 86 };
 87 
 88 class G: public virtual A
 89 {
 90 private:
 91     int data5;
 92 public:
 93     G(): data5(5){}
 94     void do_something()
 95     {
 96         printf("G\n");
 97     }
 98 };
 99 
100 class H: public F, public G
101 {
102 private:
103     int data6;
104     int data7;
105     int data8;
106 public:
107     H(): data6(6), data7(7), data8(8){}
108     void foo()
109     {
110         printf("H:foo\n");
111     }
112 };
113 int _tmain(int argc, _TCHAR* argv[])
114 {
115     C c;
116     // c.do_something(); 非法!
117 
118 
119     E e;
120     // 非虚继承时:下面三种调用都是非法的!因为“访问不明确”
121     // e.do_something();
122     // e.foo();
123     // e.func();
124 
125     void* buff[10];
126     memcpy(buff, &e, sizeof(E));
127 
128     printf(">> 查看对象结构:\n");
129     for(int i = 0; i < sizeof(E)/4; i++)
130         printf("%d\n", (unsigned int)(buff[i]));
131     printf("<< 结束!\n");
132     
133     H h;
134     h.do_something();
135     h.foo();
136     h.func();
137 
138     memcpy(buff, &h, sizeof(H));
139 
140     printf(">> 查看对象结构:\n");
141     for(int i = 0; i < sizeof(H)/4; i++)
142         printf("%d\n", (unsigned int)(buff[i]));
143     printf("<< 结束!\n");
144 
145     A* ptr = &h;
146     ptr->do_something();
147     ptr->foo();
148     ptr->func();
149 
150     system("pause");
151     return 0;
152 }

输出结果:

>> 查看对象结构:
4282340
1
31
4282308
1
32
33
<< 结束!
G
H:foo
F:func
>> 查看对象结构:
4282608
4
4283120
5
6
7
8
0
4283140
1
<< 结束!
A
H:foo
F:func
请按任意键继续. . .

 

posted @ 2013-11-03 20:27  铁甲小宝  阅读(496)  评论(0)    收藏  举报