混淆是指针和虚拟函数的内存分配

Confusion is memory allocation for pointers and virtual functions

本文关键字:函数 内存 分配 虚拟 指针      更新时间:2023-10-16

我读过关于虚拟函数的文章,但我无法理清这个概念。在下面提到的例子中。我们正在创建一个基指针,并首先分配基对象,调用函数是基类,然后分配派生对象并调用其函数。既然我们已经提到了将分配哪些对象,编译器不知道在编译过程中调用哪个对象函数吗?我不明白为什么这个决定会推迟到运行时间。我是不是错过了什么。?

#include <iostream>
using std::cout;
using std::endl;
// Virtual function selection
class Base
{
public:
   virtual void print() const
   { 
      cout << "Inside Base" << endl; 
   }
};
class Derived : public Base
{
public:
   // virtual as well
   void print() const
   { 
      cout << "Inside Derived" << endl; 
   }
};
int main()
{
   Base b;
   Derived f;
   Base* pb = &b;  // points at a Base object
   pb->print();    // call Base::print()
   pb = &f;        // points at Derived object
   pb->print();    // call Derived::print()
}

在您的特定情况下,编译器可能会找出基类指针指向的对象的类型。但是,虚拟调度机制是为编译时没有这些信息的情况而设计的。例如,

int n;
std::cin >> n;
Base b;
Derived d;
Base* pb = n == 42 ? &b : &d;

在这里,选择是基于用户输入进行的。编译器无法知道pb将指向什么。

既然我们已经提到了将分配哪些对象,编译器不知道在编译过程中调用哪个对象函数吗?我不明白为什么这个决定会推迟到运行时间。

在这种非常具体、人为的情况下,编译器可以优化所有的多态性,是的。

我是不是错过了什么。?

意识到现实生活中绝大多数代码都是而不是这么简单的想象。有无限多的C++程序,编译器没有足够的信息来执行这种优化。

根据我的理解,编译器只会在编译时查看引用类型,并绑定该类中定义和声明的函数。由于应该调用Derived->print(),您必须使print函数在基类中为虚拟函数,这样编译器将延迟绑定到运行时并使用派生类中定义的函数。

由于它是虚拟的,因此能够将函数动态绑定到正确的对象。这意味着调用函数的指针将调用被引用对象的函数。