【问题标题】:How does a pointer to virtual function differ from a pointer to a non-virtual one?指向虚函数的指针与指向非虚函数的指针有何不同?
【发布时间】:2013-08-10 15:28:07
【问题描述】:

为什么在下一段代码中需要在函数前使用“&”?

void (Mammal::*pFunc) () const=0;
pFunc=&Mammal::Move;

Move() 是基本类中的虚函数,pFunc 是指向此类中虚函数的指针。 那么为什么我们需要使用“&”呢?根据虚函数的一些特殊性质? 或者它只是语法?

【问题讨论】:

  • 使用指向成员函数的指针通常不会很好
  • 我们需要使用&,因为标准是这样规定的。
  • 指向虚函数的指针和指向非虚成员函数的指针在语法上没有区别。它们在底层实现方式不同,但程序员不应该看到这一点。

标签: c++ function pointers virtual


【解决方案1】:

一个普通函数可以只用它的地址来调用,所以指向一个普通函数的指针就是一个地址。

一个非虚函数也可以只用它的地址来调用(当然,还有this指针,通过编译器使用的任何机制传递),所以指向非虚函数的指针可能只是一个地址。

必须通过特定于编译器的机制(通常是 vtable,在对象中的已知偏移处;通过索引表找到函数的地址)和指向虚函数的指针来查找虚函数必须包含确定要调用的实际函数所需的任何信息,具体取决于对象的实际类型。

但是指向成员函数的指针必须能够处理虚函数和非虚函数,因此它将为两者的正确机制留出足够的空间,并且运行时调用将检查存储数据以找出要做什么。

一些编译器提供了另一种选择,如果您承诺绝对、肯定地从不在指针中存储指向虚函数的指针,编译器将生成更小的指针表示,并且您'当你违背诺言时,你会发现你有麻烦了。

至于为什么需要&,它是必需的。微软早期的 C++ 编译器不需要&(也不需要类名;如果你省略了它,你会得到一个指向当前对象类的成员函数的指针);他们谈到提议取消该规则,但没有成功。

【讨论】:

  • 我认为指向虚拟成员函数的指针通常由 thunk 处理,因此所有成员函数指针都使用相同的表示。成员数据指针是龙居住的地方。
  • @AlanStokes - 在某些实现上可能是。不过,这不是必需的。自从我关注这种细节已经很多年了,所以我不知道最新的实现技术或它们的广泛使用情况。
【解决方案2】:

& 是地址运算符。虽然在 C 中可以简单地指定函数的名称而不使用 this,但在 C++ 中,您应该将其与完全限定的函数名称一起使用。

如果我没记错的话,当你获取一个虚函数的地址时,编译器实际上会生成一个中间函数,然后使用它的地址来代替。当调用该中间函数时,它所要做的就是调用您指定的虚函数。

【讨论】:

  • 在 C++ 中,成员函数需要 & 和类名。 C 根本没有成员函数,因此没有任何语法来引用它们。两种语言都允许在没有 & 的情况下引用非成员函数。
【解决方案3】:

在您的第一行中,pFunc 不是指向虚函数的指针,而是指向 Mammal 中不带参数并返回 void 的 const 方法的指针。然后将 0 分配给该指针。

'&' 运算符为您提供类范围内的 Mammal::Move 方法的地址,适合分配给成员函数指针。

标准需要“&”运算符,尽管我使用的编译器不需要它。

【讨论】:

  • 编译器在代表标准方面可能会有所不同,但标准肯定需要成员函数上的&
猜你喜欢
  • 2011-10-08
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-21
相关资源
最近更新 更多