2017-11-01 5 views
0

を作るとき間違ったもので終わるのvtable、私は次のセットアップがあります複数のコール

class CRpCat : 
    public CQueryDataBase, 
    public IRpCat 
    { 
public: 
    CRpCat(); 
    virtual ~CRpCat(); 

// IRpCat 
public: 
    virtual HRESULT Initialize(); 

を.....何とか何とか.......

class CQueryDataBase : public CQueryNotify 
{ 
    // this has virtual functions, all concrete 
    virtual void OnDataChange(ULONG nRow, DBREASON eReason); 

.....何とか何とか.......

class CQueryNotify 
{ 
public: 
    // abstract signatures 
    virtual void OnDataChange(ULONG nRow, DBREASON eReason) = 0; 

......何とか何とか..............

そして最後に

class IRpCat 
{ 
public: 
    virtual HRESULT Initialize() = 0; 

だから、私は2つのクラスから派生クラスのthatsを持っており、仮想関数はどこにでもあります。派生したクラスは親クラスの1つではありません - これはダイヤモンドの問題ではありません(おそらく関連性はありますが)

ここが問題です。クラスをインスタンス化し、初期化()呼び出しを行う場合、私の代わりに)(OnDataChangeので終わる:

IRpCat *pCat = GetInstance()->GetRpCat(); 
pCat->Initialize(); 

両方初期化()とOnDataChangeの()それぞれのvtableのスロット内の最初の関数である - 私何が起こっているのか理解していないが、私はInitialize()コールがvtable [0]を通して起こっていることを知っている - しかし残念ながら、私は間違ったvtableに終わる。直感で、私は次のことを試してみました:

最初の行は、仮想にすることで、私は(正しく)(初期化で終わる)

class CRpCat : 
     public virtual CQueryDataBase, 
     public IRpCat 
     { 

二行目は、仮想することにより、私は間違ってで終わりますOnDataChangeの()

class CRpCat : 
     public CQueryDataBase, 
     public virtual IRpCat 
     { 

して初期化()の呼び出し

class CRpCat : 
     public virtual CQueryDataBase, 
     public virtual IRpCat 
     { 
を行う際に、両方の線が仮想することによって、それが例外をスローします

だから、誰かが何が起こっているか説明してもらえますか? (これはVisual Studio C++です。)それは間違いなく、vtableのレイアウト方法と関係があります。 ありがとうございました

+0

不適切なキャストのバグのようです。詳細なコードや詳細を入力してください。間違いなく、これは起こらないはずです。 – valdo

+0

私たちを表示するには[最小、**完全**、および検証可能な例](http://stackoverflow.com/help/mcve)を作成してみてください。 –

答えて

1

それを実演しました。問題は、オブジェクトがインスタンス化された方法だった。

void * p = new CRpCat(); 
IRpCat * p2 = static_cast<IRpCat *>(p); 
p2->Initialize(); 

「void *型」最初のポインタを保存し、それをキャストし、「スライス」ポインタだった - ので、奇妙な結果。皆さん、ありがとうございました。