2016-08-04 6 views
1

で失敗し、C++/CX代理人は、次のコードは、purvirtの呼び出しで失敗する理由を私は理解できない、純粋仮想コールアサーション

このabort();は、WinRTのプロジェクトはC++/CX

を使用して呼び出します
namespace Test { 
    public delegate void TickHandle(); 

    ref class Clock { 
    public: 
     event TickHandle^ Tick; 
    }; 


    ref class Base { 
    internal: 
     Base() : 
      m_clock(ref new Clock()) 
     { 
      std::cout << "Base::Base" << std::endl; 
      m_clock->Tick += ref new Test::TickHandle(this, &Test::Base::OnTick); 
      OnTick(); 
     } 
    protected: 
     virtual void Foo() = 0; 

    private: 
     Clock^ m_clock; 

     void OnTick() 
     { 
      std::cout << "Tick" << std::endl; 
     } 
    }; 

    ref class Derive : public Base{ 
    internal: 
     Derive() 
     { 
      std::cout << "Derive::Derive" << std::endl; 
     } 
    protected: 
     void Foo() override 
     { 
      std::cout << "Derive::Foo" << std::endl; 
     } 
    }; 

    void main() 
    { 
     auto y = ref new Test::Derive(); 
    } 
} 

Tickイベントへの登録が何らかの理由に純粋仮想コールと考えられているI-ドント・ノウ何を断層ラインです。

私は、この例で遊んといくつかのことに気づいた:

  1. 基本クラスは純粋仮想である場合にのみ起こる( Foo() = 0に気づく)

  2. それがあれば問題ありません。 Base::Tickが...プライベート\パブリック\は などを保護

  3. である私は(当然)からOnTick()を呼び出すことができますコンストラクタです。

誰でも説明がありますか?

+0

このコードを取得するためのスローグのビット。 QueryInterfaceは失敗します。 C++ルールは、コンストラクターの実行中にv-tableが非仮想関数を指すように要求します。 C++コンパイラは、何らかの形で、クラスに純粋な関数がないときにそのルールを回避することを知っています。抽象基本クラスでそのトリックが機能しない理由はあまり明確ではありません。回避策は、オブジェクトを構築した後に呼び出す別の関数にイベント割り当てを移動することです。 –

答えて

1

C++/CXは、COMオブジェクトを簡単にするコンパイララッパーです。これは、IUnknownを実装するオブジェクトを意味します。 Baseのコンストラクタでは、IUnknownの仮想関数テーブルはまだ初期化されていないため、すべてのエントリは「純粋仮想」です。ティックハンドラを登録しようとすると、IUnknown::AddRefを呼び出すことによってthisへの参照を追加する必要があります。これはオブジェクトが完全に構築されるまで「純粋仮想」実装を指しています。

+0

ありがとうございます、私はrefカウントが事実かもしれないと思ったが、IUnknownの部分を考えなかった。私はまだ何かを得ることはできません - Baseのコンストラクタ本体で、 'これは既にBaseを強く参考にしていますか?だから私はBase(IUnknown)の基底が初期化されていると思うだろう。もしそうなら、Tickイベントに登録しようとするとなぜ構築されないのだろう? – ZivS

+2

'IUnknown'は最終的な型がわかるまで実装できません。私は、 'ref new'が' IUnknown'を正しく実装できるように 'Derived'を最終的なテンプレートの1つにまとめていると仮定します。それまではIUnknownは純粋です。あなたはオブジェクトを構築しているので、 'this'は良いと知っていますが、COMの参照はまだ保持されていません。なぜなら、最も派生した型が完全に構築されるまで、これは本当のCOMオブジェクトです。 – nate

関連する問題