非多态情况

一. 非多态分类:
C++Primer 第三版中文版Page752有如下记载:
“当成员函数是虚拟的时候,通过一个类对象(指针或引用)而被调用的该成员函数,是在该类对象的动态类型中被定义的成员函数。”
这句话有两个元素至关重要,
a.虚成员函数
b.类对象的指针或引用
而此两点有无的组合和有四种情况:
只有a,b同时符合才能实现动态联编(((Father*)lpFson)->DisplayV()结果参考),
而其他三种情况均不符合,编译器在编译期间将确定调用函数。
编译器也是根据此两点来确定到底是否动态联编。
下面对其他三种情况非动态联编进行说明举例。
1)子类覆盖父类函数时,指向子类对象的指针强制转换成指向父类的指针,然后调用此覆盖函数时,不进行动态动态绑定。也就是调用的是父类的函数,而非子类的函数((Father*)lpFson)->Display();结果参考)。【a不符】
2)子类覆盖父类函数时,子类对象强制转换成父类,然后调用此覆盖函数时,不进行动态动态绑定。也就是调用的是父类的函数,而非子类的函数(((Father)son).DisplayV();结果参考)。【b不符】
3)子类隐藏父类函数时,子类对象强制转换成父类,然后调用此隐藏函数时,不进行动态动态绑定。也就是调用的是父类的函数,而非子类的函数(((Father)son).Display();结果参考)。【a,b都不符】       
       
代码验证:

 class Father      
 {       
 public:       
  Father(int i)     
  {       
   var1 = i;    
  }      
 public:       
  ~Father(void){};     
  void Display()     
  {      
   TRACE("Father::Display  var1 = %d/n",var1); 
  }      
  virtual  void DisplayV()    
  {      
   TRACE("Father::DisplayV  var1 = %d/n",var1); 
  }      
         
 private:       
  int var1;     
 };       
         
 //class Son      
 class Son : public  Father     
 {       
 public:       
  Son(int i,int j):Father( i)   
  {       
   var2 = j;    
  }      
 public:       
  ~Son(void){};     
  void Display()     
  {      
   TRACE("Son::Display  var2 = %d/n",var2); 
  }      
  virtual  void DisplayV()    
  {      
   TRACE("Son::DisplayV  var2 = %d/n",var2); 
  }      
 private:       
  int var2;     
  int var3;     
 };       
         
 //调用呼出函数      
 void CTianTestDlg::OnBnClickedCancel2()   
 {       
  Son son(1,2);     
  son.Display();     
  son.DisplayV();     
  ((Father)son).Display();   //输出:Father::Display  var1 = 1
  ((Father)son).DisplayV();//输出:Father::DisplayV  var1 = 1
         
  //指针运行情况     
  TRACE("----------------------------------/n"); 
  Son *lpFson = &son;    
  lpFson->Display();    
  lpFson->DisplayV();    
  ((Father*)lpFson)->Display();//输出:Father::Display  var1 = 1
  ((Father*)lpFson)->DisplayV();//输出:Son::Display  var1 = 1
 }       

         
二. 非多态实现        
1.简单理解上
编译器根据元素a和b很容易判断出来是静态编译,然后根据此时调用函数的定义类型就可以决定调用哪个函数,(进行过强制转换,就是转换后的的类的函数,未转换过的话,就是定义时候的类型)
而如果是动态编译,将根据指向的实在对象里记录的虚拟表指针,在动态运行时查虚拟表确定函数。
2.从编译器生成的汇编代码的验证:
请参考:
浅析C++中虚函数的调用及对象的内部布局
http://blog.csdn.net/starlee/archive/2008/02/13/2089358.aspx
里面有详细的汇编代码说明

 

<注>作为例外,类的构造函数在符合a,b条件时不进行动态联编,因为这个时候子类的对象还没有创建好,无法实现动态联编。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值