2016-08-16 2 views
0

私はthisを使用していくつかの困難を持って、それは私の派生クラスをスライスするようです。この例は私の問題を説明するのに役立ちます。このスライスを使用して私のオブジェクト

class A 
{ 
    A() { 
     OtherClass(*this); 
    } 

    virtual doSomething() = 0; 
} 

class B : public A 
{ 
    B() : A() {} 

    doSomething() override { 
     std::cout << "Hi!" << std::endl; 
    } 
} 

class OtherClass() 
{ 
    OtherClass(A &a) { 
     a.doSomething(); 
    } 
} 

は、いくつかの調査の後には、その使用*thisスライスクラスBのように思えます。そして、OtherClassAで純粋仮想メソッドを呼び出します。私が間違っている? Bクラスの初期化後にOtherClass(*this)を作成する必要がありますか?

答えて

2

Aのコンストラクタは、Aの純粋仮想メソッドを呼び出すOtherClassのコンストラクタを呼び出します。

残念ながら、この仮想メソッドを実装するAのサブクラスはまだ構築されていないため、結果は未定義の動作です。

注意:スーパークラスはサブクラスの前に構築されます。 Bが構築されて(純粋な仮想メソッドを実装する)ことができるようになるには、そのスーパークラスのAが完全に構築される必要があります。そのプロセスの一部として、もちろん、Aのコンストラクタが呼び出されます。

+0

'サブクラスはスーパークラスの前に構築されます'。そうですか?ベース(スーパー)クラスは、派生(サブ)クラスの前に構築されます。 –

+0

訂正しました... –

2

これはスライシングの問題ではありません。

コンストラクタ/デストラクタでは、仮想メソッドは仮想的に呼び出されません。

合理的には、オブジェクトが完全に構築されていないか、または部分的に破壊されていることです。 thisポインタは、派生クラスを指しておらず、現在構築/破棄されているクラス(この場合はA)のみを指しています。

+0

実際、 'OtherClass'では' A :: doSomething' *が仮想的に呼び出されます。しかし、オブジェクトの動的タイプはまだ調整されていないので(「A」のコーダーは終了せず、オブジェクトポイントは「A」のvtableへ)、純粋な仮想が呼び出される。 – StoryTeller

+0

@StoryTeller:コンストラクタ/デストラクタの 'this-> doSomething()'は、 'B :: doSomething()'の代わりに 'A :: doSomething()'(OPのケースでは純粋仮想呼び出し)コンパイラがそのために "変更された" * vtableを渡すことを選択した場合(ダイアモンド階層について考える))。 – Jarod42

+0

しかしこれは 'this-> doSomething()'ではありません。それは 'anotherObj-> doSoemthing()'です。 – StoryTeller

関連する問題