指向虚拟成员函数的指针.它是如何工作的?

26 c++ virtual member-function-pointers

考虑以下C++代码:

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


int main()
{
     void (A::*f)()=&A::f;
}
Run Code Online (Sandbox Code Playgroud)

如果我不得不猜测,我会说在这个上下文中的&A :: f将意味着"A的f()实现的地址",因为在指向常规成员函数和虚拟成员函数的指针之间没有明确的分离.由于A没有实现f(),这将是一个编译错误.但事实并非如此.

不仅如此.以下代码:

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

实际上会调用B :: f.

怎么会发生?

Joh*_*itb 22

它起作用,因为标准说它应该如何发生.我使用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;
}
Run Code Online (Sandbox Code Playgroud)

该程序输出1 5- 这两个函数的虚拟表条目的字节偏移量.它遵循Itanium C++ ABI,它指定了.


Ste*_*sop 10

这是关于成员函数指针的太多信息.在"表现良好的编译器"下有一些关于虚函数的东西,虽然IIRC当我读到文章时我正在浏览那部分,因为这篇文章实际上是关于用C++实现委托.

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

简短的回答是它依赖于编译器,但一种可能性是成员函数指针被实现为包含指向"thunk"函数的指针的结构,该函数进行虚拟调用.