2012-03-31 16 views
0

問題があります。 2つのクラスがあります。Cでの型キャスティングと継承

struct Base { 
    Base* retain() { 
    //retain here 
     return this; 
    } 
}; 

struct Derived : Base { 
}; 


Derived *d1 = new Derived(); 
Derived *d2 = d1->retain(); //error here: need to typecast to Derived* 
Derived *d3 = (Derived*)d1->retain(); //OK 

は私が手動で結果を型キャストする必要はありませんように、保持()関数を書き換えする方法はありますか?つまり、retain()は、派生型のオブジェクトを返す必要があります。

答えて

4
template<typename T> 
struct Base 
{ 
    T* retain() 
    { 
     return (T*)this; 
    } 
}; 

struct Derived : Base<Derived> 
{ 
}; 


Derived *d1 = new Derived(); 
Derived *d2 = d1->retain(); 

struct Base 
{ 
    template<typename T> 
    void retain(T** ptr) 
    { 
     *ptr = (T*)this; 
    } 
}; 

struct Derived : Base 
{ 
}; 

Derived *d1 = new Derived; 
Derived *d2; 
d1->retain(&d2); 
+0

これは私の答えよりも優れています。これを好む – thb

+0

ところで、最初のアプローチは["Curiously Recurring Template Pattern"(CRTP)]と呼ばれています(http://ja.wikipedia.org/wiki/Curiously_recurring_template_pattern) –

0

通常、あなたがやっていることをすると、基本クラスには仮想デストラクタがあります。これにより、実行時型の識別が可能になります。

publicなど、struct Derived : public Baseと書くこともできます。

説明仮想デストラクタを次に示します。

仮想メソッドがない単純なクラスのオブジェクトは、メモリ内のデータの集合に過ぎません。このようなオブジェクトのアドレスを持つコードは、オブジェクトを参照するだけで、そのオブジェクトが基底型か派生型かを知ることができません。

しかし、基本型に少なくとも1つの仮想メソッドがある場合、コンパイラはその型の各オブジェクトに1つの隠しポインタを追加します。このポインタは、とりわけオブジェクトの型を正確に識別するテーブルを指し示し、ポインタ上でdynamic_cast<>()および他の多態操作を可能にする。

これが初めての場合は、次に試してみることをお勧めします。ヌル仮想デストラクタvirtual ~Base() {}をBaseクラスに追加し、次にdynamic_cast<>()について読んでください。次に、Base retain()を仮想にして、Derived独自に、retain()を上書きすることもできます。

これ以上のターゲットアドバイスを得ることができない場合は、前述の内容を参考にしてください。がんばろう。また

+1

構造に対するデフォルトの継承アクセス指定子は – givi

+0

@givi公開されている:私はそれを知りませんでした。ありがとうございました。 – thb

+0

私は仮想関数と仮想デストラクタを知っています。動的キャスティングは実行時に発生し、コンパイル時にエラーが発生します。 – givi