考虑以下C ++代码:

class A
{
public:
      virtual void f()=0;
};


int main()
{
     void (A::*f)()=&A::f;
}

如果我不得不猜测,我会说,&A :: F IN此背景下,将意味着“的的实现F()的地址”,因为有定期的成员函数和指针之间没有明确的分离 - 虚拟成员函数。并且由于没有实现F(),这将是一个编译错误。然而,事实并非如此。

和不仅如此。以下代码:

void (A::*f)()=&A::f;
A *a=new B;            // B is a subclass of A, which implements f()
(a->*f)();

将实际调用B :: F。

它是如何发生的呢?

有帮助吗?

解决方案

下面是一个关于成员函数指针方式太多的信息。有一个关于虚函数的一些东西在“乖编译”,虽然IIRC当我读到的文章我是略读的那部分,由于物品实际上是关于用C实现委托++。

http://www.codeproject.com/KB/cpp/FastDelegate.aspx

简单的回答是,它依赖于编译器,但一种可能性是该成员函数指针作为含有一个指向一个结构实施了“咚”的功能,这使得虚拟呼叫。

其他提示

它的工作原理,因为标准说,这应该是如何发生的。我做了一些测试与GCC,和原来为虚函数,GCC存储虚拟表所讨论的功能的偏移字节数。

struct A { virtual void f() { } virtual void g() { } }; 
int main() { 
  union insp { 
    void (A::*pf)();
    ptrdiff_t pd[2]; 
  }; 
  insp p[] = { { &A::f }, { &A::g } }; 
  std::cout << p[0].pd[0] << " "
            << p[1].pd[0] << std::endl;
}

这方案产出1 5 - 的那些两个函数的虚拟表条目的字节偏移。它遵循安腾C ++ ABI 其指定

我不能完全肯定,但我认为这只是常规的多态行为。我认为&A::f实际上意味着在类的虚函数表函数指针的地址,这就是为什么你没有得到一个编译器错误。在虚函数表的空间仍然分配,而且是你实际上又回到了位置。

这很有意义,因为派生类基本上覆盖这些值与指针它们的功能。这就是为什么在(a->*f)()你的第二个例子工程 - f会引用在派生类中实现虚函数表

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top