多重继承:
- 非虚函数,两个基类存在满足覆盖条件的函数时,派生类无法调用其中任何一个函数。该条件只有一个要求:重名。无论返回值、参数、const类型如何,只要重名,即满足覆盖条件。
虚继承:
- 伴随虚继承衍生出来了虚基类的概念,当一个B虚继承了A时,A就是B的虚基类,虚基类的概念只存在于虚继承关系两个类之间,当此时C正常继承A时,A相对于C就不是虚基类。
- 无论虚继承还是虚基类,都与虚函数无关。
- 使用虚继承时,两个中间类都必须是虚继承于最基类,否则无论虚函数还是非虚函数,都会产生两份函数。
正常使用方法:
- 两个中间类虚继承与最基类,之后最派生类正常继承于两个中间类;
- 两个中间类必须保证不同时覆盖某个虚函数或同时覆盖某个非虚函数,否则会造成最派生类调用函数不明确;
- 此时,最派生类对象会根据这两个中间类的函数实现情况,去选择应该调用的函数,如(2)中所述,最近基类必须无冲突。
- 其实,此时最派生类所继承的是两个中间类的合集,如下图所示:
非虚继承时对象的结构,虚继承对于对象结构的影响:
非虚继承的类图:
非虚继承的实例的数据结构:
虚继承的类图:
虚继承的实例的数据结构:
输出结果分析:
程序代码:
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 "); 16 } 17 virtual void foo() 18 { 19 printf("A:foo "); 20 } 21 virtual void func() 22 { 23 printf("A:func "); 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 "); 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 "); 49 } 50 virtual void to_string() 51 { 52 printf("this is a C "); 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 "); 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 "); 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 "); 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 "); 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(">> 查看对象结构: "); 129 for(int i = 0; i < sizeof(E)/4; i++) 130 printf("%d ", (unsigned int)(buff[i])); 131 printf("<< 结束! "); 132 133 H h; 134 h.do_something(); 135 h.foo(); 136 h.func(); 137 138 memcpy(buff, &h, sizeof(H)); 139 140 printf(">> 查看对象结构: "); 141 for(int i = 0; i < sizeof(H)/4; i++) 142 printf("%d ", (unsigned int)(buff[i])); 143 printf("<< 结束! "); 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 请按任意键继续. . .