静态绑定和动态绑定

/****************************************************************************
        静态绑定:对象在声明时采用的类型,在编译期既已确定
        动态类型:通常指一个指针或引用目前所指对象的类型,是在运行期决定的
        静态绑定:绑定的是静态类型,所对应的函数或属性依赖于对象的静态类型,
发生在编译期
        动态绑定:绑定的是动态类型,所对应的函数或属性依赖于对象的动态类型,
发生在运行期

        在C++中,非虚函数一般都是静态绑定,而虚函数都是动态绑定(如此才可实现多态性)
****************************************************************************/
#if 0
#include <iostream>

class A
{
public:
        void func()
        {
                std::cout<<"A::func()\n";
        }
};

class B : public A
{
public:
        void func()
        {
                std::cout<<"B::func()\n";
        }
};

class C : public A
{
public:
        void func()
        {
                std::cout<<"C::func()\n";
        }
};

int main()
{
        C* pc = new C();  //pc的静态绑定类型和动态绑定类型均为C*
        B* pb = new B();  //pb的静态绑定和动态绑定类型均为B*
        A* pa = pc;      //pa的静态绑定类型为A*,动态绑定类型为pc的类型C*

        pa = pb;          //将pa的动态绑定类型改为B*,其静态绑定类型仍为A*
        C* pNull = NULL;  //pNull静态绑定类型为C*
        
        pa->func();
        pc->func();
        pNull->func();
        

        return 0;
}
#endif
/*----------------------------------------------------------------------
结论:
        1.如果基类A中的func函数不是虚函数,无论哪个指针对func的调用都是
在定义时的静态类型决定,早在编译期确定了.
        2.同样空指针也能调用非虚函数而不报错,所以要做空指针检查,因此静
态绑定不能实现多态。
        3.如果基类中的func函数是虚函数,那所有的调用都要等到运行是根据其
指向对象的类型才能确定,比起静态绑定自然是要有性能损失,但实现了多态。
        4.引用同样适用。

建议:
        绝对不要重新定义继承而来的非虚函数,因为这样导致函数调用由对象声明的
静态类型确定了,而和对象本身脱离了关系,没有多态,这也将给程序留下预知的
隐患和莫名奇妙的BUG.
        在动态绑定中,要注意默认参数的使用,当缺省参数和virtual函数一起使用时,
一定要谨慎。
-------------------------------------------------------------------------*/
# include <iostream>
using namespace std;

class F
{
public:
        virtual void func(int i = 1)
        {
                cout<<"F::func()"<<i<<endl;
        }
};

class E : public F
{
public:
        virtual void func(int i = 0)
        {
                cout<<"E::func()"<<i<<endl;
        }
};

void main()
{
        F* pf = new F();
        E* pe = new E();

        pf->func(); //F::func()1
        pf = pe;  //将pf的动态绑定类型改为E*
        pf->func(); //E::func()1
}

/*----------------------------------------------------------------------------
  注意:
        绝对不要重新定义一个继承而来的virtual函数的缺省参数值,因为缺省参数值都是
静态绑定的,而virtual函数确实动态绑定.
-----------------------------------------------------------------------------*/

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

 

posted @ 2017-09-04 12:43  actually96  阅读(221)  评论(0编辑  收藏  举报