class的实质 class内存分布 class 是一种特殊的 struct
在内存中 class 依旧可以看作变量的集合  
class 与 struct 遵循相同的内存对齐规则  
class 中的成员函数与成员变量是分开存放的 每个变量都有独立 的成员变量(位于栈空间或堆空间或全局数据区) 所有对象共享 类中的成员函数(位于代码段) 
 
答案都是20个字节。
那么如果我们在class中添加函数呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include  <iostream>  #include  <string>  using  namespace  std;#pragma  pack(4) class  A {     int  i;     int  j;     char  c;     double  d; public :    void  print ()       {        cout << "i = "  << i << ", "               << "j = "  << j << ", "               << "c = "  << c << ", "               << "d = "  << d << endl;     } }; struct  B {     int  i2;		     int  j2;		     char  c2;		     double  d2;	 }; #pragma  pack() int  main ()  {    A a;          cout << "sizeof(A) = "  << sizeof  (A) << endl;         cout << "sizeof(a) = "  << sizeof  (a) << endl;     cout << "sizeof(B) = "  << sizeof  (B) << endl;              a.print ();          B* p = reinterpret_cast <B*>(&a);          p->i2 = 1 ;     p->j2 = 2 ;     p->c2 = 'c' ;     p->d2 = 3 ;          a.print ();          p->i2 = 100 ;     p->j2 = 200 ;     p->c2 = 'C' ;     p->d2 = 3.14 ;          a.print ();          return  0 ; } 
 
1 2 3 4 5 6 7 8 fengyun@ubuntu:~/share$ g++ test.cpp -o test fengyun@ubuntu:~/share$ ./test  sizeof (A)   = 20 sizeof  (a) = 20 sizeof  (B) = 20 i = 0 , j = 0 , c = `, d = -2.84627e+237  i = 1 , j = 2 , c = c, d = 3  i = 100 , j = 200 , c = C, d = 3.14  
 
stuct A和class B内存排布相同。因此用指针类型转换后也可以直接访问成员变量。
运行时的对象退化为结构体 的形式
所有成员变量 在内存中依次排布 
 
成员变量间可能存在内存空隙 
 
可以通过内存地址 直接访问成员变量
 
访问权限关键字在运行时失效 
 
类中的成员函数位于代码段中 
 
调用成员函数时对象地址 作为参数隐式传递 
 
成员函数通过对象地址 访问成员变量
 
C+ + 语法规则隐藏了对象地址的传递过程   
 
 
C语言实现面向对象 用C++实现面向对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include  <iostream>  #include  <string>  using  namespace  std;class  Demo {     int  mi;     int  mj; public :    Demo (int  i, int  j)     {         mi = i;         mj = j;     }          int  getI ()       {        return  mi;     }          int  getJ ()       {        return  mj;     }          int  add (int  value)       {        return  mi + mj + value;     } }; int  main ()  {    Demo d (1 , 2 )  ;          cout << "sizeof(d) = "  << sizeof  (d) << endl;     cout << "d.getI() = "  << d.getI () << endl;     cout << "d.getJ() = "  << d.getJ () << endl;     cout << "d.add(3) = "  << d.add (3 ) << endl;          return  0 ; } 
 
1 2 3 4 5 fengyun@ubuntu:~/share$ ./test  sizeof(d) = 8 d.getI() = 1 d.getJ() = 2 d.add(3) = 6 
 
那我们如果用C语言实现同样的逻辑,那该怎么写?
C语言没有class关键字,不可以在类内写成员函数。C语言写面向对象的代码,必须手动传入对象地址 。C语言中没有private信息隐藏,我们因此定义typedef void Demo;Demo_Create返回的类型变为void*,我们无法直接通过返回的对象直接访问成员变量。
访问权限关键字在运行时失效,private 和 protected 的访问权限仅在编译时候有效。C++ 编译器在编译成员函数调用的时候,隐藏的传递了对象的地址,在成员函数的内部有了这个隐藏的地址当然可以直接访问对象的成员变量。(即编译时区分)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 struct  ClassDemo {     int  mi;     int  mj; }; Demo* Demo_Create (int  i, int  j)   {    struct  ClassDemo * ret  =  (struct ClassDemo*)malloc (sizeof (struct ClassDemo));          if ( ret != NULL  )     {         ret->mi = i;         ret->mj = j;     }          return  ret; } int  Demo_GetI (Demo* pThis)  {     struct  ClassDemo * obj  =  (struct ClassDemo*)pThis;            return  obj->mi; } int  Demo_GetJ (Demo* pThis)  {    struct  ClassDemo * obj  =  (struct ClassDemo*)pThis;           return  obj->mj; } int  Demo_Add (Demo* pThis, int  value)  {    struct  ClassDemo * obj  =  (struct ClassDemo*)pThis;           return  obj->mi + obj->mj + value; } void  Demo_Free (Demo* pThis)  {    free (pThis); } 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int  main ()  {    Demo* d = Demo_Create(1 , 2 );                       printf ("sizeof(*d) = %d" ,sizeof (*d));     printf ("d.mi = %d\n" , Demo_GetI(d));          printf ("d.mj = %d\n" , Demo_GetJ(d));          printf ("Add(3) = %d\n" , Demo_Add(d, 3 ));                        Demo_Free(d);          return  0 ; } 
 
1 2 3 4 fengyun@ubuntu:~/share$ ./test  d.mi = 1 d.mj = 2 Add(3) = 6 
 
最终打印效果一致。
小结 
C+ + 中的类对象在内存布局上与结构体相同 
成员变量和成员函数在内存中分开存放  
访问权限关键字在运行时失效  
调用成员函数时对象地址作为参数隐式传递   
 
继承对象模型 简单的C++继承对象模型 
可以观察到大小是增加了4个字节,即int类型大小。那么内存排布是怎样的呢?
我选择临时定义一个Test结构体,Test结构体内存分布如下。
并且使用强制类型转换,把Derived *指针类型转换为Test *(p指针)
用p指针修改Test对象的成员变量值。改变过后调用Derived类内的成员函数print(),观察到这样竟然也修改Derived定义的结构体的成员变量的值。这说明Test结构体内存分布布局和Derived内存分布布局是相同的。
但是按照protected的成员变量在外界应当是访问不到的啊。这是因为访问权限关键字在运行时失效,在成员函数的内部有了这个隐藏的地址当然可以直接访问对象的成员变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include  <iostream>  #include  <string>  using  namespace  std;#progma pack(4) class  Demo { protected :    int  mi;     int  mj; }; class  Derived  :  public  Demo{     int  mk; public :    Derived (int  i, int  j, int  k)     {         mi = i;         mj = j;         mk = k;     }          void  print ()       {        cout << "mi = "  << mi << ", "               << "mj = "  << mj << ", "               << "mk = "  << mk << endl;     } }; struct  Test {     int  mi;     int  mj;     int  mk; }; #progma pack() int  main ()  {    cout << "sizeof(Demo) = "  << sizeof  (Demo) << endl;              cout << "sizeof(Derived) = "  << sizeof  (Derived) << endl;            Derived d (1 , 2 , 3 )  ;     Test* p = reinterpret_cast <Test*>(&d);          cout << "Before changing ..."  << endl;          d.print ();          p->mi = 10 ;     p->mj = 20 ;     p->mk = 30 ;          cout << "After changing ..."  << endl;          d.print ();          return  0 ; } 
 
继承而来的内存排布和Test结构体是一样的。
1 2 3 4 5 6 7 fengyun@ubuntu:~/share$ ./test  sizeof(Demo) = 8 sizeof(Derived) = 12 Before changing ... mi = 1, mj = 2, mk = 3 After changing ... mi = 10, mj = 20, mk = 30 
 
虚函数的继承对象模型 C+ + 多态的实现原理(相同的行为方式【调用语句】,不同的行为结果)
当类中声明虚函数 时 , 编译器会在类中生成一个虚函数表  
虚函数表是一个存储成员函数地址的数据结构  
虚函数表是由编译器自动生成与维护的  
virtual 成员函数 会被编译器放入虚函数表中  
存在虚函数时 ,每个对象中都有一个指向虚函数表的指针 
 
C++的多态就是依靠虚函数
当生成一个类对象的时候,编译器自动为这个对象“塞”一个指针变量,而这个指针指向创建的虚函数表。
具体调用类内的函数时:p->add(v)
具体调用过程:
三次寻址,因此虚函数调用效率低于 普通成员函数。
接着来验证一下带有虚函数的继承对象模型的内存分布:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include  <iostream>  #include  <string>  using  namespace  std;class  Demo { protected :    int  mi;     int  mj; public :    virtual  void  print ()       {        cout << "mi = "  << mi << ", "               << "mj = "  << mj << endl;     } }; class  Derived  :  public  Demo{     int  mk; public :    Derived (int  i, int  j, int  k)     {         mi = i;         mj = j;         mk = k;     }          void  print ()       {        cout << "mi = "  << mi << ", "               << "mj = "  << mj << ", "               << "mk = "  << mk << endl;     } }; struct  Test {     void * p;     int  mi;     int  mj;     int  mk; }; int  main ()  {    cout << "sizeof(Demo) = "  << sizeof  (Demo) << endl;              cout << "sizeof(Derived) = "  << sizeof  (Derived) << endl;            Derived d (1 , 2 , 3 )  ;     Test* p = reinterpret_cast <Test*>(&d);          cout << "Before changing ..."  << endl;          d.print ();          p->mi = 10 ;     p->mj = 20 ;     p->mk = 30 ;          cout << "After changing ..."  << endl;          d.print ();          return  0 ; } 
 
1 2 3 4 5 6 7 fengyun@ubuntu:~/share$ ./test  sizeof(Demo) = 16 sizeof(Derived) = 24 Before changing ... mi = 1, mj = 2, mk = 3 After changing ... mi = 10, mj = 20, mk = 30 
 
ubantu64位的情况下,Demo类和Derived类都比之前多了8个字节,即一个指针的字节大小。
并且注意Test结构类型
1 2 3 4 5 6 7 struct Test {     void* p;     int mi;     int mj;     int mk; }; 
 
说明类的虚函数表指针默认放在类的成员变量之前 。
C语言实现继承与多态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #ifndef  _51_2_H_ #define  _51_2_H_ typedef  void  Demo;typedef  void  Derived;Demo* Demo_Create (int  i, int  j)  ;int  Demo_GetI (Demo* pThis)  ;int  Demo_GetJ (Demo* pThis)  ;int  Demo_Add (Demo* pThis, int  value)  ;void  Demo_Free (Demo* pThis)  ;Derived* Derived_Create (int  i, int  j, int  k)  ;int  Derived_GetK (Derived* pThis)  ;int  Derived_Add (Derived* pThis, int  value)  ;#endif  
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 #include  "51-2.h"  #include  "malloc.h"  static  int  Demo_Virtual_Add (Demo* pThis, int  value)  ;static  int  Derived_Virtual_Add (Demo* pThis, int  value)  ;struct  VTable      // 2. 定义虚函数表数据结构{     int  (*pAdd)(void *, int );    }; struct  ClassDemo {     struct  VTable * vptr ;           int  mi;     int  mj; }; struct  ClassDerived {     struct  ClassDemo  d ;     int  mk; }; static  struct  VTable  g_Demo_vtbl  =  {     Demo_Virtual_Add }; static  struct  VTable  g_Derived_vtbl  =  {     Derived_Virtual_Add }; Demo* Demo_Create (int  i, int  j)   {    struct  ClassDemo * ret  =  (struct ClassDemo*)malloc (sizeof (struct ClassDemo));      if ( ret != NULL  )     {         ret->vptr = &g_Demo_vtbl;            ret->mi = i;         ret->mj = j;     }          return  ret; } int  Demo_GetI (Demo* pThis)  {     struct  ClassDemo * obj  =  (struct ClassDemo*)pThis;          return  obj->mi; } int  Demo_GetJ (Demo* pThis)  {    struct  ClassDemo * obj  =  (struct ClassDemo*)pThis;     return  obj->mj; } static  int  Demo_Virtual_Add (Demo* pThis, int  value)  {    struct  ClassDemo * obj  =  (struct ClassDemo*)pThis;          return  obj->mi + obj->mj + value; } int  Demo_Add (Demo* pThis, int  value)  {    struct  ClassDemo * obj  =  (struct ClassDemo*)pThis;     return  obj->vptr->pAdd(pThis, value); } void  Demo_Free (Demo* pThis)  {    free (pThis); } Derived* Derived_Create (int  i, int  j, int  k)   {    struct  ClassDerived * ret  =  (struct ClassDerived*)malloc (sizeof (struct ClassDerived));          if ( ret != NULL  )     {         ret->d.vptr = &g_Derived_vtbl;         ret->d.mi = i;         ret->d.mj = j;         ret->mk = k;     }          return  ret; } int  Derived_GetK (Derived* pThis)  {    struct  ClassDerived * obj  =  (struct ClassDerived*)pThis;          return  obj->mk; } static  int  Derived_Virtual_Add (Demo* pThis, int  value)  {    struct  ClassDerived * obj  =  (struct ClassDerived*)pThis;      return  obj->mk + value; } int  Derived_Add (Derived* pThis, int  value)  {       struct  ClassDerived * obj  =  (struct ClassDerived*)pThis;          return  obj->d.vptr->pAdd(pThis, value); } 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include  "stdio.h"  #include  "51-2.h"  void  run (Demo* p, int  v)  {    int  r = Demo_Add(p, v);          printf ("r = %d\n" , r); } int  main ()  {    Demo* pb = Demo_Create(1 , 2 );     Derived* pd = Derived_Create(1 , 22 , 333 );          printf ("pb->add(3) = %d\n" , Demo_Add(pb, 3 ));     printf ("pd->add(3) = %d\n" , Derived_Add(pd, 3 ));          run(pb, 3 );     run(pd, 3 );          Demo_Free(pb);     Demo_Free(pd);          return  0 ; } 
 
多态 多态的概念 只要是子类对象,我们需要默认调用子类重写过后的自定义的函数 而不是执行父类继承的版本函数
面向对象中期望的行为 - 根据实际的对象类型判断如何调用重写函数 - 父类指针( 引用 ) 指向父类对象则调用父类中定义的函数 • 父类指针( 引用 ) 指向子类对象则调用子类中定义的重写函数  
面向对象中的多态的概念
根据实际的对象类型决定 函数调用的具体目标 
同样的调用语句 在实际运行时有多种不同的表现形态    
 
C+ + 语言直接支持多态的概念
通过使用 virtual 关键字对多态进行支持 
被 virtual 声明的函数被重写后具有多态特性 
被 virtual 声明的函数叫做虚函数   
 
由于继承的关系,父类中vitrual关键字也会被子类继承(我们在子类中写不写virtual都无所谓)
多态的意义 
在程序运行过程中展现出动态 的特性 
函数重写必须多态实现 (virtual),否则没有意义 
多态是面向对象组件化程序设计 的基础特性   
 
理论中的概念 静态联编:在程序的编译期间就能确定具体的函数调用–比如:函数重载 动态联编:在程序实际运行后才能确定具体的函数调用–比如:函数重写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #include  <iostream>  #include  <string>  using  namespace  std;class  Parent { public :    virtual  void  func ()       {        cout << "Parent::void func()"  << endl;     }          virtual  void  func (int  i)       {        cout << "Parent::void func(int i) : "  << i << endl;     }          virtual  void  func (int  i, int  j)       {        cout << "Parent::void func(int i, int j) : "  << "("  << i << ", "  << j << ")"  << endl;     } }; class  Child  :  public  Parent{ public :    void  func (int  i, int  j)       {        cout << "Child::void func(int i, int j) : "  << i + j << endl;     }          void  func (int  i, int  j, int  k)       {        cout << "Child::void func(int i, int j, int k) : "  << i + j + k << endl;     } }; void  run (Parent* p)  {    p->func (1 , 2 );                              } int  main ()  {    Parent p;          p.func ();              p.func (1 );             p.func (1 , 2 );                    cout << endl;          Child c;          c.func (1 , 2 );               cout << endl;          run (&p);		       run (&c);		            return  0 ; } 
 
1 2 3 4 5 6 7 8 9 10 fengyun@ubuntu:~/share$ g++ test.cpp -o test  fengyun@ubuntu:~/share$ ./test  Parent::void func() Parent::void func(int i) : 1 Parent::void func(int i, int j) : (1, 2) Child::void func(int i, int j) : 3 Parent::void func(int i, int j) : (1, 2) Child::void func(int i, int j) : 3 
 
小结 
函数重写只可能发生在父类与子类之间 
根据实际对象的类型确定调用的具体函数 
virtual 关键字是 C+ + 中支持多态的唯一方式 
被重写的虚函数可表现出多态的特性   
 
被遗弃的多重继承 C+ + 支持编写多重继承的代码
一个子类可以拥有多个父类 
子类拥有所有父类的成员变量 
子类继承所有父类的成员函数 
子类对象可以当作任意父类对象使用   
 
多重继承问题一:对象地址不同 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 #include  <iostream>  #include  <string>  using  namespace  std;class  BaseA {     int  ma; public :    BaseA (int  a)     {         ma = a;     }     int  getA ()       {        return  ma;     } }; class  BaseB {     int  mb; public :    BaseB (int  b)     {         mb = b;     }     int  getB ()       {        return  mb;     } }; class  Derived  :  public  BaseA, public  BaseB{     int  mc; public :    Derived (int  a, int  b, int  c) : BaseA (a), BaseB (b)     {         mc = c;     }     int  getC ()       {        return  mc;     }     void  print ()       {        cout << "ma = "  << getA () << ", "               << "mb = "  << getB () << ", "               << "mc = "  << mc << endl;     } }; int  main ()  {    cout << "sizeof(Derived) = "  << sizeof  (Derived) << endl;              Derived d (1 , 2 , 3 )  ;          d.print ();          cout << "d.getA() = "  << d.getA () << endl;     cout << "d.getB() = "  << d.getB () << endl;     cout << "d.getC() = "  << d.getC () << endl;          cout << endl;          BaseA* pa = &d;     BaseB* pb = &d;          cout << "pa->getA() = "  << pa->getA () << endl;     cout << "pb->getB() = "  << pb->getB () << endl;          cout << endl;          void * paa = pa;     void * pbb = pb;               if ( paa == pbb )     {         cout << "Pointer to the same object!"  << endl;      }     else      {         cout << "Error"  << endl;     }          cout << "pa = "  << pa << endl;     cout << "pb = "  << pb << endl;     cout << "paa = "  << paa << endl;     cout << "pbb = "  << pbb << endl;           return  0 ; } 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 fengyun@ubuntu:~/share$ ./test  sizeof(Derived) = 12 ma = 1, mb = 2, mc = 3 d.getA() = 1 d.getB() = 2 d.getC() = 3 pa->getA() = 1 pb->getB() = 2 Error pa = 0x7ffd163e869c pb = 0x7ffd163e86a0 paa = 0x7ffd163e869c pbb = 0x7ffd163e86a0 
 
通过多重继承得到的对象可能拥有”不 同 的 地 址 “ !! 解决方案 : 无  
多重继承问题二:虚继承 多重继承可能产生冗余的成员
当多重继承关系出现闭合时将产生数据冗余的问题 ! ! ! !  
解决方案 : 虚继承  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #include  <iostream>  #include  <string>  using  namespace  std;class  People {     string m_name;     int  m_age; public :    People (string name, int  age)     {         m_name = name;         m_age = age;     }     void  print ()       {        cout << "Name = "  << m_name << ", "               << "Age = "  << m_age << endl;     } }; class  Teacher  :  virtual  public  People{ public :    Teacher (string name, int  age) : People (name, age)     {     } }; class  Student  :  virtual  public  People{ public :    Student (string name, int  age) : People (name, age)     {     } }; class  Doctor  :  public  Teacher, public  Student{ public :    Doctor (string name, int  age) : Teacher (name, age), Student (name, age), People (name, age)     {     } }; int  main ()  {    Doctor d ("fengyun" , 20 )  ;          d.print ();          return  0 ; } 
 
虚继承: 
中间层父类不再关心顶层父类的初始化  
虚继承能够解决数据冗余问题 
最终子类必须直接调用顶层父类的构造函数   
 
问 题 :  当架构设计中需要继承时,无法确定使用直接继承还是虚继承
多重继承问题三:多个虚函数表 
需要进行强制类型转换时 , C+ + 中推荐使用新式类型转换关键字 ! ! 解决方案 : dynamic_cast  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #include  <iostream>  #include  <string>  using  namespace  std;class  BaseA { public :    virtual  void  funcA ()       {        cout << "BaseA::funcA()"  << endl;     } }; class  BaseB { public :    virtual  void  funcB ()       {        cout << "BaseB::funcB()"  << endl;     } }; class  Derived  :  public  BaseA, public  BaseB{ }; int  main ()  {    Derived d;     BaseA* pa = &d;     BaseB* pb = &d;     BaseB* pbe = (BaseB*)pa;         BaseB* pbc = dynamic_cast <BaseB*>(pa);          cout << "sizeof(d) = "  << sizeof  (d) << endl;          cout << "Using pa to call funcA()..."  << endl;          pa->funcA ();          cout << "Using pb to call funcB()..."  << endl;          pb->funcB ();          cout << "Using pbc to call funcB()..."  << endl;          pbc->funcB ();          cout << endl;          cout << "pa = "  << pa << endl;     cout << "pb = "  << pb << endl;     cout << "pbe = "  << pbe << endl;     cout << "pbc = "  << pbc << endl;          return  0 ; } 
 
工程中的多重继承 单继承某个类 + 实现(多个) 接口  
一些有用的工程建议
先继承自一个父类,然后实现多个接口 
父类中提供equal()成员函数 
equal()成员函数用于判断指针是否指向当前对象 
与多重继承相关的强制类型转换用dynamic_cast完成   
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 #include  <iostream>  #include  <string>  using  namespace  std;class  Base { protected :    int  mi; public :    Base (int  i)     {         mi = i;     }     int  getI ()       {        return  mi;     }     bool  equal (Base* obj)       {        return  (this  == obj);     } }; class  Interface1 { public :    virtual  void  add (int  i)   = 0 ;     virtual  void  minus (int  i)   = 0 ; }; class  Interface2 { public :    virtual  void  multiply (int  i)   = 0 ;     virtual  void  divide (int  i)   = 0 ; }; class  Derived  :  public  Base, public  Interface1, public  Interface2{ public :    Derived (int  i) : Base (i)     {     }     void  add (int  i)       {        mi += i;     }     void  minus (int  i)       {        mi -= i;     }     void  multiply (int  i)       {        mi *= i;     }     void  divide (int  i)       {        if ( i != 0  )         {             mi /= i;         }     } }; int  main ()  {    Derived d (100 )  ;     Derived* p = &d;     Interface1* pInt1 = &d;     Interface2* pInt2 = &d;          cout << "p->getI() = "  << p->getI () << endl;              pInt1->add (10 );     pInt2->divide (11 );     pInt1->minus (5 );     pInt2->multiply (8 );          cout << "p->getI() = "  << p->getI () << endl;              cout << endl;          cout << "pInt1 == p : "  << p->equal (dynamic_cast <Base*>(pInt1)) << endl;     cout << "pInt2 == p : "  << p->equal (dynamic_cast <Base*>(pInt2)) << endl;          return  0 ; } 
 
关于虚函数的问题 构造函数是否可以成为虚函数 ? 析构函数是否可以成为虚函数 ?  
构造函数不可能成为虚函数 在构造函数执行结束后 , 虚函数表指针才会被正确的初始化 
析构函数可以成为虚函数 建议在设计类时将析构函数声明为虚函数   
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #include  <iostream>  #include  <string>  using  namespace  std;class  Base { public :    Base ()     {         cout << "Base()"  << endl;                  func ();     }          virtual  void  func ()        {        cout << "Base::func()"  << endl;     }          virtual  ~Base ()     {         func ();                  cout << "~Base()"  << endl;     } }; class  Derived  :  public  Base{ public :    Derived ()     {         cout << "Derived()"  << endl;                  func ();     }          virtual  void  func ()       {        cout << "Derived::func()"  << endl;     }          ~Derived ()     {         func ();                  cout << "~Derived()"  << endl;     } }; int  main ()  {    Base* p = new  Derived ();                    delete  p;          return  0 ; } 
 
如果不将析构函数设为虚函数,p指针类型是Base*,delete p将会执行Base的析构函数
构造函数中是否可以发生多态? 析构函数中是否可以发生多态?  
构造函数中不可能发生多态行为,只调用当前类中的版本  在构造函数执行时 , 虚函数表指针未被正确初始化  
析构函数中不可能发生多态行为,只调用当前类中的版本  在析构函数执行时 , 虚函数表指针已经被销毁