指针虚拟成员函数。 它是如何工作的?(Pointers to virtual member fu

2019-06-25 03:40发布

考虑下面的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。

它是如何发生的呢?

Answer 1:

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

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

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



Answer 2:

它的工作原理,因为标准说,这应该是如何发生的。 我做了一些测试与海湾合作委员会,它原来的虚函数,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, 它指定 。



Answer 3:

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

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



文章来源: Pointers to virtual member functions. How does it work?