@RocketMagnet - 这是对您的另一个问题的回应,该问题被标记为重复。我在回答这个问题,而不是这个问题。
通常,指向成员函数的 C++ 指针不能在类层次结构中移植。也就是说,您通常可以侥幸逃脱。例如:
#include <iostream>
using std::cout;
class A { public: int x; };
class B { public: int y; };
class C : public B, public A { public: void foo(){ cout << "a.x == " << x << "\n";}};
int main() {
typedef void (A::*pmf_t)();
C c; c.x = 42; c.y = -1;
pmf_t mf = static_cast<pmf_t>(&C::foo);
(c.*mf)();
}
编译这段代码,编译器正确地抱怨:
$ cl /EHsc /Zi /nologo pmf.cpp
pmf.cpp
pmf.cpp(15) : warning C4407: cast between different pointer to member representations, compiler may generate incorrect code
$
所以要回答“为什么 C++ 没有指向成员函数的指针在 void-class 上?” 是这个虚构的基类没有成员,所以没有任何值可以安全地分配给它!“void (C:: )()”和“void (void:: )()”是互不兼容的类型。
现在,我敢打赌你在想“等等,我之前已经很好地投射了成员函数指针!” 是的,你可能有,使用 reinterpret_cast 和单一继承。这与其他重新解释演员表属于同一类别:
#include <iostream>
using std::cout;
class A { public: int x; };
class B { public: int y; };
class C : public B, public A { public: void foo(){ cout << "a.x == " << x << "\n";}};
class D { public: int z; };
int main() {
C c; c.x = 42; c.y = -1;
// this will print -1
D& d = reinterpret_cast<D&>(c);
cout << "d.z == " << d.z << "\n";
}
因此,如果void (void::*)()
确实存在,但没有什么可以安全/便携地分配给它。
void (*)(void*)
传统上,您可以在任何您想使用的地方使用签名函数void (void::*)()
,因为虽然成员函数指针不能很好地在继承层次结构上下转换,但 void 指针确实可以很好地转换。反而:
#include <iostream>
using std::cout;
class A { public: int x; };
class B { public: int y; };
class C : public B, public A { public: void foo(){ cout << "a.x == " << x << "\n";}};
void do_foo(void* ptrToC){
C* c = static_cast<C*>(ptrToC);
c->foo();
}
int main() {
typedef void (*pf_t)(void*);
C c; c.x = 42; c.y = -1;
pf_t f = do_foo;
f(&c);
}
所以对于你的问题。为什么 C++ 不支持这种类型的转换。指向成员函数的指针类型已经必须处理虚拟与非虚拟基类,以及虚拟与非虚拟成员函数,它们都属于同一类型,在某些平台上将它们膨胀到 4*sizeof(void*)。我认为因为它会使指向成员函数的指针的实现进一步复杂化,而原始函数指针已经很好地解决了这个问题。
就像其他人评论的那样,C++ 为库编写者提供了足够的工具来完成这项工作,然后像你我这样的“普通”程序员应该使用这些库而不是为这些细节操心。
编辑:标记的社区维基。请仅编辑以包含对 C++ 标准的相关引用,并添加斜体。(特别是在我的理解错误的地方添加对标准的引用!^_^)