假设我有两个C++类:
class A
{
public:
A() { fn(); }
virtual void fn() { _n = 1; }
int getn() { return _n; }
protected:
int _n;
};
class B : public A
{
public:
B() : A() {}
virtual void fn() { _n = 2; }
};
Run Code Online (Sandbox Code Playgroud)
如果我写下面的代码:
int main()
{
B b;
int n = b.getn();
}
Run Code Online (Sandbox Code Playgroud)
人们可能期望将n其设置为2.
事实证明,n设置为1.为什么?
我读回来(可能是在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'指针,调用相应的函数(其地址位于偏移量).我不知道如何证明这一点,因为标准没有说明任何事情!