关于基类和派生类之间的指针混合的思考

来源:互联网 发布:中国自主软件 编辑:程序博客网 时间:2024/06/10 16:44

  基类类型的指针可以指向派生类的对象,但是派生类类型的指针不能指向基类的对象。
  或者说一个基类对象的地址不能用来初始化一个派生类类型的指针。
  如下:
  class B
  {
  };
  
  class D:public B
  {
  };
  
  .........
  B ob;
  D od;
  B * pB=&od;
  D * pD=&ob; // error !
  
  更一般的思考,基类代表着最少的确定的信息,而派生类则代表着较多的确定的信息。
  一个基类的指针可以指向一个派生类的对象,意味着一个指针可以指向一个容纳了多于自己期望的信息量的对象。那么当这样的一个操作发生后,这个指针就可以做出一些额外的操作,这些操作是它在被定义的时候并没有期望能够做到的,或者说并没有想到的。
  与此相对的是,一个派生类的指针则不能指向一个基类的对象。因为如果可以这样做的话,那么这个派生类的指针在被定义的时候所期望能做的所有事情中将有一部分不再能够做到,因为在它指向的那个基类的对象中根本就没有提供那些在派生类派生的时候新增加的方法。但是C++则保证一个指针定义之后,它至少要能够做和它被期望做的一样多的事情。那么,派生类指针指向基类对象的意图当然不能被允许。
  看看下面的这个例子:
  #include
  #include
  using namespace std;
  class B
  {
  public:
   inline void print(){ cout<<"class B print\n";}
  };
  
  class D:public B
  {
  public:
   inline void print(){ cout<<"class D print\n";}
  };
  
  void foo(B *pb)
  {
   pb->print();
  }
  
  int main(int argc ,char argv[])
  {
   B ob;
   D od;
   B *pB1=&ob;
   B *pB2=&od;
   foo(pB1);
   foo(pB2);
  
   return 0;
  }
  
  程序的输出应该是:
  class B print
  class B print //为什么这里不是 class D print 呢?
  
  D中的print和B中的print是什么关系呢?


************************************************************

下面做一个变形,有意让类之间发生 隐藏 而不是 覆盖。

class B
{
public:
void print() { cout<<" B class"<<endl; } //这里没有了virtual,将发生 隐藏。
};

class D:public B
{
public:
void print() { cout<<" D class"<<endl; } //隐藏B中的print,是 隐藏。
};

然后这样使用:

D dd;
B* Bp=&dd;
D* Dp=&dd;

Bp->print();
Dp->print();
// 使用方式和上面完全一样

输出结果为:
B class
D class

这里B中的print出现了(输出 B class),也就是说,在发生隐藏后,如果你强迫D(派生类)的对象去按照B(基类)的方式来表现,那么被B中被隐藏的那个函数将被实际调用。
0 0