2011-01-01 17 views
2

私は基本クラスAと公開クラスBを持っていると仮定して、AオブジェクトをBのA基本クラスサブオブジェクトにどのように割り当てる必要がありますか?派生クラスオブジェクトに基本クラスオブジェクトを割り当てる方法は?

class A {...}; 
class B : public A {...}; 
A a(..); 
B b(..); 
static_cast<A&>(b) = a; ??? 

Bの代入演算子を記述しないと実行できますか? bをA &にキャスティングする際に問題がありますか?その規格に準拠していますか?

+4

なぜこれをやりたいですか? –

+0

それは良い質問です。そのような割り当ての意味はどうでしょうか? – Kos

+1

MS VC ATLライブラリにはいくつかの用途があります。 – 9dan

答えて

3

基本クラスオブジェクトを派生クラスオブジェクトに割り当てる理由と方法を示すもう1つの答えを書く。

struct TimeMachineThing_Data { 
.. 
.. 
}; 

class TimeMachineThing : private TimeMachineThing_Data 
{ 
    static std::stack<TimeMachineThing_Data> m_stateHistory; 

    void SaveState() { 
     m_stateHistory.push_back(static_cast<TimeMachineThing_Data&>(*this)); 
    } 

    void RestoreState() { 
     static_cast<TimeMachineThing_Data&>(*this) = m_stateHistory.front(); 
     m_stateHistory.pop_front(); 
    } 
}; 

これは非常に有用で完全に正当です。

(ここではこれだけの内部TimeMachineThingは、IS-TimeMachinetime_Data、民間の継承である)


もう一つ。

struct StructWithHundresField { 
    string title; 
    string author; 
    ... 

    StructWithHundresField() { 
    ... 
    } 
}; 

class EasyResetClass : public StructWithHundresField { 
    int not_reset_this_attriute; 
public: 
    void ResetToInitialStateAtAnyTime() { 
    static_cast<StructWithHundresField&>(*this) = StructWithHundresField(); 
    } 
} 
+1

これはめったに便利なパターンではありません。可能であれば、個人の継承よりも構成を優先する必要があります。 –

0

AオブジェクトをBオブジェクトに特にコピーする代入演算子が必要だと思います。

一般に、同じタイプのオブジェクトをコピーするときは、いずれかの方法を使用することをお勧めします。しかし、異なるタイプのオブジェクトは、それをさらに重要にします。

1

(他のOOP言語と同様に)継承はIs-A関係を確立します。

Bが公にA、B = A.

を継承する場合は、必ず任意の心配なし参照にBのインスタンスをキャストすることができ、あります。

+0

意味があります。私はメモリレイアウトの潜在的な問題についてのみ心配していました。なぜなら、そのようなアサイメントが常にC++で動作しなければならない理由を何とか見つけることができないからです。 – andriej

+0

-1:@ 9danそれは**偽です**。メモリBはAとは異なります。したがって、B = Aを実行すると、AのスライスだけがBにコピーされます。結果は判りません。 **多態性は、ポインタと参照のみを使用して動作します** –

+0

@Stephane私の答えでは、具体的な単語やフレーズは何ですか?私がBの記憶の一部を修正しようとすると、本当に私はその割り当ての結果を予測できませんでしたか?あなたは型平等とデータ平等を誤解しましたか? – 9dan

4

これは本当に悪い考えです。 Aはベース、Bは派生型です。 BをAにキャストすると、Aの代入演算子が使用されます。これは、余分な派生データには触れません。その割り当ての最後に、bAが含まれていても、まだタイプBと見なされます。これは継承が使用される方法の反対です。

行をb = reinterpret_cast<B&>(a);に変更するとさらに悪化します。それでは、aBであり、無効なメモリを読み込んでいると思われるでしょう。

あなたが本当にしたい、この種の代入を行いたい場合は、次の

class B : public A { 
    B& operator= (const A& a) { ... } 
}; 

次に、あなたがAからの情報をコピーするための関数を記述し、何とか派生型では、余分な情報を扱うことができますB、プラスこれは、あなたは、単に書くことができるようになる:

b = a; 
+0

"これは余分な派生データのいずれにも触れないだろう" - それが私が望むものならば、それはどうやって悪い考えですか? – andriej

+1

データの一部しか割り当てていないので、悪い考えです。私。 'static_cast (b)= a;という代入をすると' A 'にメンバー 'p、q'と' B'がメンバー 'r'を追加すると、' p、q'を代入して 'r'手つかず。これは、基本的には不完全な割り当てなので、あなたが望むものではない可能性が最も高いです。だから私はそれを言えるかもしれません "これは本当に悪い考えですが、リスクを理解すれば、それを行う方法があります。" – Tim

+0

私はこれを説明する方法を失いました。オブジェクト指向プログラミングの基本的で基本的な側面です。 BがAを継承する場合、BはAです(いくつかの追加された側面があります)。 – 9dan

2

が、これは良い考えであるかどうかを約1分間考えてみてください。 BがAをサブクラス化する場合、すべてのBはAですが、すべてのAはBではないことに注意してください。たとえば、すべての犬は哺乳動物ですが、すべての哺乳類が犬ではありません。具体的なBオブジェクトがある場合は、それをAオブジェクトに設定しようとすると、ほとんどの場合、数学的には明確に定義されません。さらに、C++の世界では、BオブジェクトがBとして静的に型付けされているので、それをB型であることを止めるような形でA型のオブジェクトに割り当てることはできません。最高で、あなたは上書きしますB個の特定部分のいずれも変更することなく、B個のオブジェクトのA部分だけを表示する。

0

割り当ては共変2項演算子であり、したがって仮想関数では正しく機能しないことを知っておくべきです。これはほとんどのバイナリ演算子に当てはまりますが、代入はC++言語の一部であるため特殊です。

オブジェクト指向を使用している場合は、オブジェクトはコピー不可能で、常にポインタで表される必要があります。オブジェクトのアイデンティティの一意性はOOの中心です:オブジェクトは値ではなく、にはというユニークな値(そのアドレス)があります。

値で遊んでいる場合は、適切な概念である機能プログラミング(FP)を使用する必要があります。それはクロージャ(アプリケーションオブジェクト)、スイッチ、テンプレート、バリアントなどです。

これらを混合する前に、それぞれを十分に理解してください。一般に、FPはOOを包含しているので、一般的な方法論もある:OOは、特殊な状況では安全な動的ディスパッチを提供する特殊なケースである。 OOディスパッチは、束縛されていないサブタイプのセットを処理することを意味しますが、プロパティ(1つのバリアント引数、つまりオブジェクトを持つ関数)にのみ適用され、高次のもの(バリアント引数が複数ある関数)代入は単なる別の2関数なので、仮想関数でディスパッチすることはできません。

関連する問題