c++ 静态绑定、动态绑定

c++ 静态绑定和动态绑定

  C++ 中有两种不同的函数调用方式:静态绑定和动态绑定。

静态绑定

  静态绑定是指在编译时确定调用哪个函数。也就是说,编译器会根据函数调用的名称和参数类型来确定要调用的函数。这种方式也被称为静态多态或编译时多态。

静态绑定适用于以下情况:

  1. 在编译时已经知道调用哪个函数。
  2. 函数的名称和参数类型是确定的。
  3. 函数调用的目标是一个静态类型的对象。

例如:

class Shape {
public:
    void draw() {
        cout << "Drawing shape" << endl;
    }
};

class Circle : public Shape {
public:
    void draw() {
        cout << "Drawing circle" << endl;
    }
};

int main() {
    Circle c;
    Shape* s = &c;
    s->draw(); // 静态绑定,输出 Drawing shape
    return 0;
}

  上述代码中,调用s->draw()函数时,由于s的静态类型是Shape*,因此编译器会使用静态绑定来调用Shape::draw()函数,而不是Circle::draw()函数。

动态绑定

  动态绑定是指在运行时确定调用哪个函数。也就是说,编译器不确定要调用哪个函数,而是将函数调用委托给运行时系统来决定。这种方式也被称为动态多态或运行时多态。

动态绑定适用于以下情况:

  1. 在运行时才知道调用哪个函数。
  2. 函数的名称和参数类型不确定,只有在运行时才能确定。
  3. 函数调用的目标是一个动态类型的对象。

例如:

class Shape {
public:
    virtual void draw() {
        cout << "Drawing shape" << endl;
    }
};

class Circle : public Shape {
public:
    void draw() {
        cout << "Drawing circle" << endl;
    }
};

int main() {
    Circle c;
    Shape* s = &c;
    s->draw(); // 动态绑定,输出 Drawing circle
    return 0;
}

  上述代码中,调用s->draw()函数时,由于s的动态类型是Circle,因此运行时系统会使用动态绑定来调用Circle::draw()函数,而不是Shape::draw()函数。这就是C++中的虚函数机制,通过在函数前加上virtual关键字来实现。

空指针调用函数

#include <iostream>
using namespace std;

class test {
public:
    void show() { cout << "I'm test" << endl; }
};

int main()
{
    test* t = nullptr;
    t->show(); // 输出 I'm test
}

  上面的代码是可以正常运行的。

  在 c++ 中,类的成员函数并不与特定对象绑定,所有成员函数共用一份成员函数体,当程序编译后,成员函数的地址即已经确定。(静态绑定)

  当调用 t->show()时,实际上执行的代码是 test::show(this), 成员函数 show() 的地址在编译器就已经确定。test::show(this) 操作相当于执行了一个函数,传入的参数为 nullptr。而在 show() 函数中没有用到 this 指针,所以程序正常运行,不会报错。

如果把代码改成下面这样,程序就会 crash

#include <iostream>
using namespace std;

class test  {
public:
    void show() {
        a = 2;
    }

private:
    int a;
};

int main()
{
    test* t = nullptr;
    t->show();
}

在 show() 函数里会执行 this->a = 2;, 而 this 指针是 nullptr, 所以会报错。

所以,空指针也不能调用虚函数,因为虚函数的地址是动态绑定的,在运行时要通过虚函数表指针 this->vptr 找到对象对应的类的虚函数表(vtbl)。此时 this 为空,就会报错

posted @   卑以自牧lq  阅读(259)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示