美文网首页
静态动态绑定

静态动态绑定

作者: 404Not_Found | 来源:发表于2021-09-04 12:42 被阅读0次
  • 作者: 雪山肥鱼
  • 时间:20210905 12:00
  • 目的: 理解静态动态绑定概念

静态与动态绑定

//静态与d动态
class Base
{
public:
};

class Derive :public Base
{
public:
};

class Derive2 :public Base
{
public:
};


int main(int argc, char ** argv)
{
    //静态类型, 对象定义的类型,编译期间是能确定好的,定义的是什么,就是什么
    Base base;// 定义的类型就是Base
    Derive derive;
    Base * pBase;
    Base *pbase2 = new Derive(); //类型也是确定的 是Base *
    Base *pbase3 = new Derive2(); //类型也是确定的 是Base *

    //动态类型,只有指针和引用才有此类做法,运行的时候才有
    //pBase 类型 飘忽不变
    pBase = pbase2;
    pBase = pbase3;


    return 0;
}

静态类型:编译期间就已经定了。可以理解为执行文件中就已经写死了。即使像也是静态绑定

Base *pbase2 = new Derive();

动态绑定,类型飘忽不定

函数的动静态绑定

普通成员函数

相比于上个例子中的代码,子类与父类增加了相同的成员函数

class Base
{
public:
    void myfunc()
    {
        cout << "Base::myfun()" << endl;
    }
};

class Derive :public Base
{
public:
    void myfunc()
    {
        cout << "Derive::myfun()" << endl;
    }
};

class Derive2 :public Base
{
public:
    void myfunc()
    {
        cout << "Derive2::myfun()" << endl;
    }
};


int main(int argc, char ** argv)
{

    Derive derive;
    Derive* pderive = &derive;
    pderive->myfunc();//Derive::myfunc
    
    Base*pbase = &derive;
    pbase->myfunc();//Base::myfunc
    
    return 0;
}
  • 函数的静态绑定:
    绑定的静态类型,所对应的函数或者属性依赖于对象的静态类型,发生在编译期间
    普通函数均为静态绑定
  • 函数的动态绑定
    所对应的函数或者属性依赖于对象的动态类型,发生在运行期间
    虚函数 - 动态绑定
    例子中的myfun()是标准的普通成员函数,普通函数,到底调用哪个,取决于调用者的类型

代码规范: 不能在子类中重新定义一个基类中的普通成员函数

虚函数

增加虚函数代码

class Base
{
public:
    void myfunc()
    {
        cout << "Base::myfun()" << endl;
    }
    virtual void myVirFunc() {
        cout << "Base:: myVirFunc()" << endl;
    }
};

class Derive :public Base
{
public:
    void myfunc()
    {
        cout << "Derive::myfun()" << endl;
    }
    virtual void myVirFunc() {
        cout << "Derive:: myVirFunc()" << endl;
    }
};

class Derive2 :public Base
{
public:
    void myfunc()
    {
        cout << "Derive2::myfun()" << endl;
    }

    virtual void myVirFunc() {
        cout << "Derive2:: myVirFunc()" << endl;
    }
};


int main(int argc, char ** argv)
{

    Derive derive;
    Derive* pderive = &derive;
    
    Base*pbase = &derive;
    Base base;
    pderive->myVirFunc();//Derive
    pbase->myVirFunc();//Derive

    pbase = &base;
    pbase->myVirFunc(); //Base


    return 0;
}

非常明显的动态绑定。

虚函数中默认参数的坑

class Base
{
public:
    void myfunc()
    {
        cout << "Base::myfun()" << endl;
    }
    virtual void myVirFunc(int value =1) {
        cout << "Base:: myVirFunc(), value = " << value << endl;
    }
};

class Derive :public Base
{
public:
    void myfunc()
    {
        cout << "Derive::myfun()" << endl;
    }
    virtual void myVirFunc(int value =2) {
        cout << "Derive:: myVirFunc(), value= " << value << endl;
    }
};

int main(int argc, char ** argv)
{
    Derive derive;
    Derive* pderive = &derive;
    
    Base*pbase = &derive;
    Base base;
    pderive->myVirFunc();//Derive default value = 2
    pbase->myVirFunc();//Derive default value = 1;

    pbase = &base;
    pbase->myVirFunc(); //Base default value= 1;
    return 0;
}

虚函数的默认参数是静态绑定的。生命的类型是谁,就用谁的虚函数默认参数。

谈多态

  • 代码实现
    调用虚函数,走虚函数表这条路,则是多态,如果不是,则非多态
  • 表现形式
  1. 父类有虚函数,子类必有虚函数表,子类重写父类的虚函数
  2. 父类指针 or 引用 指向子类地址 or 子类对象
  3. 父类指针 or 引用 调用子类中重写的虚函数时,能看到多态,调用的实际是子类的虚函数。

多态注定要依靠虚函数的

class A
{
public:
    virtual void myvirfun()
    {
        printf("A:myvirfun()");
    }
};

class B:public A
{
public:
};

int main(int argc, char ** argv)
{

    A *pa = new A();
    pa->myvirfun();//多态

    A a;
    //进入反汇编 就2行代码
    a.myvirfun();//非多态

    A*ppa = &a;
    ppa->myvirfun();//多态

    B b;
    b.myvirfun();

    return 0;
}

注意:

A a;
a.myvirfun();

非多态,进入反汇编,则只能看到2行代码 调用的是 A::myvirfun();

虚函数的调用

小测试 虚函数位置

问: 虚函数i() 在虚函数表什么位置

class Base
{
public:
    virtual void f()
    {
        cout << "Base::f()" << endl;
    }
    virtual void g()
    {
        cout << "Base::g()" << endl;
    }
    virtual void h()
    {
        cout << "Base::h()" << endl;
    }
};

class Derive :public Base
{
public:
    virtual void i()
    {
        cout << "Derive::self i()" << endl;
    }
    virtual void g()
    {
        cout << "Derive::g()" << endl;
    }
    void myselffunc(){}
};

int main(int argc, char**argv)
{
    //一 单继承下的虚函数测试
    //由反汇编测试可知,i 在子类虚函数表的最后。看图即可。
    Derive myDerive;
    Derive *pMyDerive = &myDerive;
    pMyDerive->f();
    pMyDerive->g();
    pMyDerive->h();
    pMyDerive->i();

    return 0;
}

打断点,在反汇编中可以观察到,子类自己的虚函数i()在虚函数表的最后

虚函数调用代码(编译器视角)

class Base
{
public:
    virtual void f()
    {
        cout << "Base::f()" << endl;
    }
    virtual void g()
    {
        cout << "Base::g()" << endl;
    }
    virtual void h()
    {
        cout << "Base::h()" << endl;
    }
};

class Derive :public Base
{
public:
    virtual void i()
    {
        cout << "Derive::self i()" << endl;
    }
    virtual void g()
    {
        cout << "Derive::g()" << endl;
    }
    void myselffunc(){}
};

int main(int argc, char**argv)
{
    Base *pb = new Derive();
    pb->g();
    /*
    (*pb->vptr[1])(pb); 1.传入this指针,2.虚函数表中每个虚函数的位置已经定死啦。    
    */
    //我们需要知道的是运行期间,pb调用哪个虚函数表

    Derive myderive;
    Base &mb = myderive;
    mb.g();
    return 0;
}
  1. 虚函数表中,每隔虚函数的位置都已经写死在可执行文件中
  2. 继承中,确认 pb 调用哪个虚函数表是关键(多继承中会用到)

vptr 的生成

vptr 编译时候生成,编译器的在构造函数中插入了给vptr 的赋值代码
所以构造函数不可以为虚函数,构造函数中就是要构造虚函数表的。把构造函数搞成虚函数毫无意义的。
子类中如果没有任何虚函数,不会复用父类的虚函数表,还会另起炉灶,弄一份一模一样的虚函数表

相关文章

  • angular 模板里面绑定属性

    1. 绑定静态属性 static property example 2. 绑定动态属性 动态属性绑定要用 [] /...

  • 第十一条 消息传递机制 objc_msgSend

    静态绑定/动态绑定# 静态绑定,就是在编译期就能决定运行时所调用的函数。动态绑定,就是在运行期才能确定调用函数。 ...

  • 程序语言基础知识

    把一个方法与其所在的类/对象关联起来叫做方法的绑定,绑定分为静态绑定(前期绑定)和动态绑定(后期绑定)。 静态绑定...

  • C++动态绑定和静态绑定

    动态绑定和静态绑定 静态绑定是编译期间就可以确定的类型 动态绑定则只能在运行时确定 用C++描述轿车和卡车 可以抽...

  • 实用的设计模式-双分派模式

    双向分派模式-java版实现 原创一个man一个man今天 先聊聊动态绑定和静态绑定 动态绑定 动态绑定是指程序在...

  • Java静态绑定与动态绑定

    目录介绍 01.什么是绑定 02.静态和动态绑定 03.辅助理解jvm图 04.动态绑定编译原理 05.动态绑定运...

  • GEEKBAND C++ 面向对象高级编程(第四周)

    C++ 动态绑定和静态绑定 首先明确四个名词定义: 静态类型:对象在声明时的类型,编译期就能确定 动态类型:指针或...

  • 动态绑定和静态绑定

    绑定指的是把方法名和对应的方法联系在一起。什么时候需要绑定呢? 方法有重载时。因为有多个同名方法,所以根据参数列表...

  • 动态绑定和静态绑定

  • 静态绑定和动态绑定

    绑定:指的是一个方法的调用与方法所在的类(方法主体)关联起来。(其实就是具体调用哪个方法)在java中,两种绑定方...

网友评论

      本文标题:静态动态绑定

      本文链接:https://www.haomeiwen.com/subject/crdjwltx.html