指针虚拟成员函数。它是如何工作的?
-
23-08-2019 - |
题
考虑以下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
会引用在派生类中实现虚函数表
不隶属于 StackOverflow