我遇到了在Microsoft Visual C++ 2003下运行我的C++程序时看起来非常烦人的错误,但它可能只是我做错了所以我想把它扔出去看看是否有人有任何想法.
我有这样的类的层次结构(完全一样 - 例如在实际代码中没有多重继承):
class CWaitable { public: void WakeWaiters() const { CDifferentClass::Get()->DoStuff(this); // Breakpoint here } }; class CMotion : public CWaitable { virtual void NotUsedInThisExampleButPertinentBecauseItsVirtual() { } }; class CMotionWalk : public CMotion { ... }; void AnnoyingFunctionThatBreaks(CMotion* pMotion) { pMotion->WakeWaiters(); }
好的,所以我用"CMotionWalk"实例调用"AnnoyingFunctionThatBreaks"(例如调试器说它是0x06716fe0),一切似乎都很好.但当我进入它时,对于调用"DoStuff"的断点,'this'指针与pMotion指针的值不同,我调用了方法(例如,现在调试器说一个字更高 - 0x06716fe4).
换句话说:pMotion的值为0x06716fe0,但是当我调用一个方法时,该方法将'this'视为0x06716fe4.
我不只是生气吗?这很奇怪,对吧?
我相信你只是看到编译器构建vtable的方式的工件.我怀疑CMotion具有它自己的虚函数,因此你最终得到派生对象中的偏移量以获得基础对象.因此,不同的指针.
如果它正在工作(即如果这不会产生崩溃,并且对象外没有指针)那么我不会太担心它.
CMotion类是否正在派生其他包含虚函数的类?我发现this指针不随你发布的代码而改变,但是如果你有这样的层次结构它会改变:
class Test { public: virtual void f() { } }; class CWaitable { public: void WakeWaiters() const { const CWaitable* p = this; } }; class CMotion : public CWaitable, Test { }; class CMotionWalk : public CMotion { public: }; void AnnoyingFunctionThatBreaks(CMotion* pMotion) { pMotion->WakeWaiters(); }
我相信这是因为CMotion类的多重继承和CMotion中的vtable指针指向Test :: f()