Abh*_*hay 5 c++ inheritance templates
我读回来(可能是在clc ++.moderated),虚拟函数调用可以被模板化.我尝试了以下几行.
#include <iostream>
template<class T, class FUN>
void callVirtual(T& t, FUN f){
(*t.*f)();
}
struct Base{
virtual ~Base(){}
virtual void sayHi()=0;
};
struct Derived : public Base{
void sayHi(){
std::cout << "Hi!" << std::endl;
}
};
void Test(){
Base* ptr = new Derived;
callVirtual(ptr,&Base::sayHi);
}
int main()
{
Test();
return 0;
}
Output:
Hi!
Run Code Online (Sandbox Code Playgroud)
虽然在编译时给定纯虚基本成员方法的地址,但是在运行时调用正确的方法的模板化方法.在标准C++中获取纯虚拟成员的地址是否合法?
提前致谢
编辑1:我删除了问题的第二部分'它是如何工作的?'.看起来这是引起注意的东西.
编辑2:我搜索了clc ++.版主并发现了这个链接(http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/5ddde8cf1ae59a0d).似乎是因为标准不限制它,所以它是有效的.
编辑3:在阅读了codeproject文章后(感谢ovanes),我认为编译器会做一些魔术.由于虚函数是通过vtable(特定于编译器)实现的,因此获取虚函数的地址总是会给出vtable中的偏移量.根据所使用的'this'指针,调用相应的函数(其地址位于偏移量).我不知道如何证明这一点,因为标准没有说明任何事情!
我猜它是未定义的。我在规范中找不到任何内容。
虚拟方法是使用称为vtable 的概念来实现的。
我想说它是编译器实现特定的。我真的认为它是纯虚拟的并不重要,如果它只是虚拟的也会发生同样的情况。
我刚刚使用 Visual Studio 2008 编译了您的代码并反汇编了 exe。VS2008 所做的是创建一个 thunk 函数,使用传入的“this”指针跳转到 vtable 条目。
这是对 callVirtual 模板函数的设置和调用。
push offset j_??_9Base@@$B3AE ; void (__thiscall *)(Base *)
lea eax, [ebp+ptr]
push eax ; Base **
call j_??$callVirtual@PAUBase@@P81@AEXXZ@@YAXAAPAUBase@@P80@AEXXZ@Z ; callVirtual<Base *,void (Base::*)(void)>(Base * &,void (Base::*)(void))
Run Code Online (Sandbox Code Playgroud)
因此它将函数指针传递给 thunk 函数: j_??_9Base@@$B3AE
; void __thiscall Base___vcall_(Base *)
j_??_9Base@@$B3AE proc near
jmp ??_9Base@@$B3AE ; [thunk]: Base::`vcall'{4,{flat}}
j_??_9Base@@$B3AE endp
Run Code Online (Sandbox Code Playgroud)
thunk 函数所做的就是使用 vtable 跳转到真正的类方法。