21xrx.com
2024-11-25 01:18:45 Monday
登录
文章检索 我的文章 写文章
C++中的动态绑定、静态绑定与虚函数表
2023-07-05 03:06:35 深夜i     --     --
C++ 动态绑定 静态绑定 虚函数表

C++是一种强类型的面向对象编程语言,它提供了一种称为动态绑定的特性,允许在程序执行时根据运行时的对象类型来选择调用哪个函数。而另一种称为静态绑定的特性,则允许在编译时确定调用哪个函数。这两种绑定方式,都是通过虚函数表这个概念来实现的。

虚函数是父类中被声明为虚拟的函数,其特征是在基类中被声明为虚函数的函数可以被覆盖,实现运行时多态性。C++编译器通过创建一个虚函数表来实现这个能力。虚函数表是一个指针数组,其中每个指针指向相应的虚拟函数的地址。每个对象都有一个指向虚函数表的指针,点运算符像访问普通变量一样访问虚函数。

静态绑定:

静态绑定是指在编译时已经确定了调用哪个函数。在静态绑定中,函数的调用是根据函数的声明类型来确定的,这种绑定方式也常称为早绑定或前期绑定。例如:

 C++

class Base {

public:

  void print() {

    cout << "Base::print()" << endl;

  }

};

class Derived : public Base {

public:

  void print() {

    cout << "Derived::print()" << endl;

  }

};

int main() {

  Base b;

  Derived d;

  Base* ptr_b = &d;

  // 静态绑定,调用Base::print(),因为ptr_b的声明类型是Base*

  ptr_b->print();

  

  // 静态绑定,调用Derived::print()

  d.print();

}

动态绑定:

动态绑定是指在程序执行时根据运行时的对象类型来选择调用哪个函数。在动态绑定中,函数的调用是根据函数的实际类型来确定的,这种方式也常称为晚绑定或后期绑定。例如:

 C++

class Base {

public:

  virtual void print() {

    cout << "Base::print()" << endl;

  }

};

class Derived : public Base {

public:

  void print() {

    cout << "Derived::print()" << endl;

  }

};

int main() {

  Base b;

  Derived d;

  Base* ptr_b = &d;

  // 动态绑定,调用Derived::print(),因为ptr_b指向的是Derived对象

  ptr_b->print();

  

  // 静态绑定,调用Derived::print()

  d.print();

}

需要注意的是,为了使动态绑定生效,必须将虚函数声明为虚函数。在基类中声明了虚函数后,派生类如果要重写该函数,则可以通过在函数前面添加 virtual 关键字来覆盖基类的函数。同时,在派生类中覆盖虚函数时,函数的签名必须与基类中的虚函数完全相同。

虚函数表:

虚函数表是一种用于实现动态绑定的技术。每个包含虚函数的类都有一个虚函数表,它是一个指向虚函数地址的指针数组。虚函数表与类的对象一起存储在内存中,因此每个对象都可以访问虚函数表。

虚函数表的结构与顺序是由编译器决定的,它包含了该类中所有的虚函数。这些函数指针按照它们在声明时出现的顺序排列,如果派生类重写了某个虚函数,则它在虚函数表中的位置与基类中的位置不同。

在程序执行时,每个对象都有一个指向该对象类的虚函数表的指针,该指针称为虚表指针。通过虚表指针,程序可以访问虚函数表中存储的地址,从而实现动态绑定。

总结:

在 C++ 中,动态绑定和静态绑定是两个非常重要的概念,它们分别用于在程序运行时和编译时确定函数调用的方式。虚函数表则是实现动态绑定的技术,它允许在运行时选择哪个函数应该调用。在面向对象编程中,深入理解这些概念对于开发高效、可维护的程序非常重要。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复