动态绑定与继承:不得不去想细节

75 篇文章 0 订阅
72 篇文章 0 订阅

C++动态绑定,也就是在一个点上会发生~~~~~~~~~~~

 

这个点就是:

 

         p->f();

 

看上面的函数:

 

当p去寻找f()的时候,

 

发现f()是虚函数,

 

这个时候:

 

p开始进行自我反省,它发现了所指向的对象的类型后,调用相关的实现。

 

把p强制转换为派生类的this,然后传给这个函数!

  

整个过程p本身没有发生类型转换,只是说:

 

         把自己作为了派生类的指针传给了隐藏的this形参;

 

 

 

总结如下:

       

1.      c++是强类型语言,不去转换类型,它就永远不会自动转换。

 

2.      转换发生在对函数的参数传递过程中,我们无法控制。

 

有两个东西可以控制强制类型转换:

 

         typeid

 

         dynamic_cast

 

这两个东西被称为C++运行时:

 

对于带虚函数的类来说:

 

          动态绑定发生在运行时期,

 

         而typeid和dynamic_cast;目的是获取对象的实际类型和转换类型,因此也发生在运行时期。

 

 

例如:

  

 

       class A{

          f();

 

       }

       class B:A{

         g();

        }

 

A* pA=new B();

 

if(B* p=dynamic_cast<B*>(pA))

 

p.g();

 

else

 

throw new dynamic_cast error();

 

 

 

#include <cstdlib>
#include <iostream>

using namespace std;

class A{
      
      };
class B:public A{
      public :
     void  f(){
           cout<<"Hello!"<<endl;
           }
      };
int main(int argc, char *argv[])
{
    A *pA;
    ((B*)pA)->f();
    system("PAUSE");
    return EXIT_SUCCESS;
}

 

对于上面的代码我想说的是:如果感觉强制转换很无奈!~~~~那么可以把这些强制转换进行封装:

 

 

 

 经过测试下面的代码,没有任何输出:

 

 

#include <cstdlib>
#include <iostream>

using namespace std;

class A{
friend class C;      
      };
class B:public A{
friend class C;
      public :
     void  f(){
           cout<<"Hello!"<<endl;
           }
      };
class C{
         A* pa;
  public:
         C(A* p_a):pa(p_a){   
              };
         void f(){
              if(typeid(B).name()==typeid(*pa).name())
              ((B*)pa)->f();
              else {
              }
         }    
};
int main(int argc, char *argv[])
{
    C c(new B());
    c.f();
    system("PAUSE");
    return EXIT_SUCCESS;
}

 

现在在A里面添加虚函数:

 

 

#include <cstdlib>
#include <iostream>

using namespace std;
class A{
      enum _NOINITMYA{a,b};
private:
      virtual void myf(_NOINITMYA b1=b){}; 
friend class C;      
      };
class B:public A{
friend class C;
      public :
     void  f(){
           cout<<"Hello!"<<endl;
           }
      };
class C{
         A* pa;
  public:
         C(A* p_a):pa(p_a){   
              };
         void f(){
              if(typeid(B).name()==typeid(*pa).name())
              ((B*)pa)->f();
              else {
              }
         }    
};
int main(int argc, char *argv[])
{
    C c(new B());
    c.f();
    system("PAUSE");
    return EXIT_SUCCESS;
}

 

 

从上面可以看到。c.f()有了结果。传递的参数实际类型为A,那么就会有如下结果:

 

 

#include <cstdlib>
#include <iostream>

using namespace std;
class A{
      enum _NOINITMYA{a,b};
private:
      virtual void myf(_NOINITMYA b1=b){}; 
friend class C;      
      };
class B:public A{
friend class C;
      public :
     void  f(){
           cout<<"Hello!"<<endl;
           }
      };
class C{
         A* pa;
  public:
         C(A* p_a):pa(p_a){   
              };
         void f(){
              if(typeid(B).name()==typeid(*pa).name())
              ((B*)pa)->f();
              else {
          // throw new DYNAMIC_CAST_ERROR();
              }
         }    
};
int main(int argc, char *argv[])
{
    C c(new B());
    c.f();
    C c1(new A());
    c1.f();
    system("PAUSE");
    return EXIT_SUCCESS;
}

 

上面的代码中,c1.f()无结果。其实这是一个错误,直接throw一个类型转换的错误。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值