Compiler Warning (level 1) C4407

cast between different pointer to member representations, compiler may generate incorrect code

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中修改的是成员变量的值,实际上这时候可能已经内存越界了,谁知道你改写了哪个对象的内存。
posted @ 2013-07-03 20:41  avexer  阅读(354)  评论(0编辑  收藏  举报