将指针指向派生类指向指针指向基类的方法是合法的,即使基类没有声明任何方法,特别是的“铸造”的方法是通过型基类的对象被调用,如follows:将指向派生类的方法的指针投射到指向基类的方法的指针
// works in VS 2008 and g++ 4.5.3
struct Base
{
};
struct Fuu : public Base
{
void bar(){ std::cout << "Fuu::bar" << std::endl; }
void bax(){ std::cout << "Fuu::bax" << std::endl; }
};
struct Foo : public Base
{
void bar(){ std::cout << "Foo::bar" << std::endl; }
void bax(){ std::cout << "Foo::bax" << std::endl; }
};
typedef void (Base::*PtrToMethod)();
int main()
{
PtrToMethod ptr1 = (PtrToMethod) &Foo::bax;
PtrToMethod ptr2 = (PtrToMethod) &Fuu::bax;
Base *f1 = new Foo;
Base *f2 = new Fuu;
(f1->*ptr1)();
(f2->*ptr2)();
}
对于“普通”指针,该规则被称为“协方差”:您可以将“派生*”转换为“基本*”(因为“派生”是“基本”),而不是相反方向(因为“ Base *'不一定指向'Derived')。对于_pointers-to-member_,这个规则被称为“contravariance”,并且基本上是与之相反的:您可以将'T Base :: *'转换为'T Derived :: *'(因为'Base'的成员也是存在于一个Derived'对象中)而不是其他方式(因为'Derived'可以将成员添加到'Base'中)。另外_please_不使用C风格演员:他们不安全,不清楚,难以发现。 –
精细打印:您的示例虽然编译和“有效”,但可能不合法。或者将'Base *''f1'强制转换为'Foo *'(如果你确定的话''static_cast'',如果你不需要''dynamic_cast''但是它需要'Base'至少有一个'virtual'函数] ),或者添加虚拟功能到'Base'的公共接口。 –