基本的に、純粋な仮想クラス Base と、Base を継承する具象クラス Derived があります。次に、メモリの一部を割り当て、単純なキャストを介して Derived の配列として扱います。次に、= を使用して配列にデータを入力します。最後に、配列をループして、Base で宣言され、Derived で定義されている仮想メソッド GetIndex を呼び出そうとします。
問題は、Base の vtable へのポインターを読み取ろうとしてアクセス違反の例外が発生することです (Visual Studio のデバッグでは、これは __vfptr として表示され、常に 0xbaadf00d です)。
以下は、私が遭遇している問題の簡単な例です。
#include "stdafx.h"
#include "windows.h"
struct Base
{
virtual int GetIndex() const = 0;
};
struct Derived : public Base
{
int index;
Derived()
{
static int test = 0;
index = test++;
}
int GetIndex() const
{
return index;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int count = 4;
// Also fails with malloc
Derived* pDerived = (Derived*)HeapAlloc(GetProcessHeap(), 0, sizeof(Derived) * count);
for (int i = 0; i < count; i++)
{
Derived t;
pDerived[i] = t;
}
// Should print 0 1 2 3
for (int i = 0; i < count; i++)
{
Base& lc = pDerived[i];
printf("%d\n", lc.GetIndex()); // FAIL!
}
return 0;
}
この動作は、HeapAlloc または malloc を介してメモリを割り当てる場合にのみ発生します。new[] を使用すると、正常に動作します。(また、cstor は前に 4 回呼び出されているため、出力は 4 5 6 7 です。)