Box2D物理エンジンを使用するゲームを作成してきましたが、スタックポインター(ESP)と多重継承で奇妙なことに遭遇しました。最小限のコードで再現できましたが、多重継承で使用するクラスを宣言する順序によって、プログラムがクラッシュするかどうかが決まるようです。
#include <iostream>
#include <string.h>
using namespace std;
class IPhysicsObject
{
public:
virtual void Collide(IPhysicsObject *other, float angle, int pos)=0;
};
class IBoardFeature
{
public:
IBoardFeature(){};
~IBoardFeature(){};
virtual bool OnAttach(int x){ return true; }
virtual bool Update(int x, float dt)=0;
};
/*
class CScorezone : public IBoardFeature, public IPhysicsObject // this breaks !!!
class CScorezone : public IPhysicsObject, public IBoardFeature // this works !!!
*/
class CScorezone : public IBoardFeature, public IPhysicsObject
{
public:
CScorezone(){}
~CScorezone(void){}
virtual bool Update(int x, float dt)
{
return true;
}
virtual void Collide(IPhysicsObject *other, float angle, int pos)
{
}
virtual bool OnAttach(int x){ return true; }
};
int main(int argc, char *argv[])
{
CScorezone *scoreZone = new CScorezone();
CScorezone *otherZone = new CScorezone();
void *voidZone = scoreZone;
IPhysicsObject *physZone = static_cast<IPhysicsObject*>(voidZone);
physZone->Collide(otherZone, 10, 1);
delete scoreZone;
delete otherZone;
// wait for user input
int x;
cin >> x;
return 0;
}
これをデバッグモードで実行すると、次のエラーが発生します
実行時チェックの失敗#0-ESPの値は、関数呼び出し全体で適切に保存されませんでした。これは通常、ある呼び出し規約で宣言された関数を、別の呼び出し規約で宣言された関数ポインターで呼び出した結果です。
次のコード行にステップインすると、次のようになります。
physZone->Collide(otherZone, 10, 1);
CScoreZone::CollideではなくCScoreZone::OnAttachに入っていることに気づきました。どうしてこれなの?CScoreZoneの継承の順序を変更すると、正常に機能します
class CScorezone : public IPhysicsObject, public IBoardFeature
WindowsXPのVS2005SP2(8.0.50727.768)で実行しています。何か案は?