2013-02-11 7 views
5
class a //my base abstract class 
{ 
public: 
virtual void foo() = 0; 
}; 

class b : public a //my child class with new member object 
{ 
public: 
void foo() 
{} 
int obj; 
}; 

int main() 
{ 
b bee; 
a * ptr = &bee; 
ptr->obj; //ERROR: class a has no member named "obj" 
} 

私の質問は、子クラス( "a")を指すベースクラス( "a")へのポインタを持っていると "obj" ")オブジェクト?キャスティングはそのトリックをすべきだと知っていますが、私はより良い解決策を探しています。基本クラスへのポインタを使用して子クラスメンバにアクセスする

+0

いくつかのコンテキストが役立ちます。なぜそれをしたいのですか?キャストがオプションでない場合、派生クラスに仮想関数オーバーライドを持たなければならず、そのメンバへの参照またはポインタが返されます。しかし、それは一般的にカプセル化を破壊する。これにより、派生したクラスメンバに基本クラスへのポインタを使用してアクセスする必要がある理由がわかります。 – Void

+0

@Voidおそらくあなたは正しいです、私はデザインを変更する必要があります。 – user1873947

答えて

7

dynamic_cast<>演算子を使用すると、aへのポインタをbへのポインタに変換できます。変換は、オブジェクトの実行時の型がptrによって指された場合にのみ成功しますbで、あなたが変換した後に結果を確認する必要がありますので、そうでない場合はnullポインタを返します。あなたはそれを保証することができる場合

b* p = dynamic_cast<b*>(ptr); 
if (p != nullptr) 
{ 
    // It is safe to dereference p 
    p->foo(); 
} 

ptrが指すオブジェクトのタイプはbですが、この場合(仮想継承が関係しないため)、static_cast<>を使用することもできます。これは、コンパイル時に実行されるオーバーヘッドが少なくなります。

あなたも auto型推論を使用して、以下のシンタックスシュガー

if (Base* x = dynamic_cast<Base*>(x)) { 
    // do something with \c x now that we know its defined  
} 

およびC++ 11でを使用することができますGCCやクランで

b* p = static_cast<b*>(ptr); 
// You are assuming ptr points to an instance of b. If your assumption is 
// correct, dereferencing p is safe 
p->foo(); 
3

継承階層をキャストする必要があります。実際にキャストしようとしているオブジェクトが予想されるタイプの場合、タイプセーフな方法でチェックできるように、適切なタイプにdynamic_castを使用するようにケースを調整します。

+0

私はdynamic_castについては考えていませんでした。タイプセーフなので問題を解決するはずです。 – user1873947

1

(およびVisual Studioで、私は思う)、

でもよりよいです
if (auto x = dynamic_cast<Base*>(x)) { 
    // do something with \c x now that we know its defined  
} 

、最終的に私たちがして制限したい場合は、読み取り専用アクセス

if (const auto x = dynamic_cast<Base*>(x)) { 
    // read something from \c x now that we know its defined  
} 

これはxのスコープをif節の中に制限することに注意してください。ifelse ifを使って、複数の連続したdynamic_castを連続して実行すると便利です。