An incorrect cast was detected.
C4407 can be generated because of compiler conformance work that was done in Visual C++ 2005. Pointer-to-member now requires a qualified name and the address-of operator (&).
C4407 can occur if you cast between a multiple inheritance pointer-to-member to a single inheritance pointer-to-member. Sometimes this can work, but sometimes it can’t because the single inheritance pointer-to-member representation doesn’t hold sufficient information. Compiling with the /vmm might help (for more information, see /vmm, /vms, /vmv (General Purpose Representation)). You can also try rearranging your base classes; the compiler is detecting a loss of information in the conversion because a base class is at a non-zero offset from the derived.
The following sample generates C4407:
// C4407.cpp
// compile with: /W1 /c
struct C1 {};
struct C2 {};
struct C3 : C1, C2 {}; /** 这里如果交换C2与C1的顺序即可消除警告 */
typedef void(C3::*PMF_C3)();
typedef void(C2::*PMF_C2)();
PMF_C2 f1(PMF_C3 pmf) {
return (PMF_C2)pmf; // C4407, change type of cast,
// or reverse base class inheritance of C3 (i.e. : C2, C1)
}
这两天在用cocos2d-x在写游戏,里面有些类似下面的代码:
struct CCObject
{
typedef void (CCObject::*pmfn)(float);
CCObject* _obj;
pmfn _pmfn;
void some_func(CCObject* obj, pmfn fn)
{
_obj = obj;
_pmfn = fn;
}
void exec()
{
(_obj->*_pmfn)(1.0f);
}
}
struct some_sub
: public CCObject
{
void _init()
{
some_func(this, (CCObject::pmfn)&some_sub::some_callback);
}
void some_callback(float)
{
}
};
目前,上面的代码是没有任何bug的,因为在some_sub::_init方法中,this的值与隐式转换后的CCObject*是相等的。
但是,在引入多重继承后,可能会出现Bug,因为this指针与转换后的CCObject*可能会不相等(与继承列表顺序有关),此时some_callback这个函数还是会被调用,但是这个成员函数的this参数确是错的!你以为你在some_callback中修改的是成员变量的值,实际上这时候可能已经内存越界了,谁知道你改写了哪个对象的内存。