2017-01-12 4 views
-2

私は以下のコードのようなことをしようとしています。 Noteは、BaseModelを継承するクラスです。ある時点でインスタンスにBaseModelインスタンスを割り当てますが、後で最初のメモを取り戻そうとすると、それは不可能なようです。なぜC++で基本クラスから子クラスにキャストできないのですか?

std::vector<Note> notes; 

Note note; 
notes.push_back(note); 

BaseModel model = Note(); // OK 
notes.push_back(model); // Error even though `model` is a `Note` 
Note note2 = (Note)model; // Also error, cannot get the `Note` instance back 

私はポインタで作業することができますが、なぜ値で動作しないのか理解したいと思います。何か案が?

+1

'model'の初期化は既にオブジェクトのスライスを行います...' model'は 'Note'ではありません。引数として 'BaseModel' const referenceをとる' Note'にコンストラクタを追加してみてください...ここで何が起こっているのか分かります。 – hyde

+0

'notes.push_back(model); //モデルが「Note」であってもエラーです。うーん、そうではありません。モデルを 'BaseModel'と宣言しました。 (私はあなたの命名規則が正当で、 'BaseModel'が' Note'の基底であると仮定しています) – Borgleader

+1

_ポインタで作業することができますが、なぜそれが参照ではうまくいかないのか理解したいと思います。 _それは**参照を使って動作します**。あなたは参照を使用していません**。 –

答えて

3

あなたのコードには、オブジェクトがある限り、C++の理解が不足していることが示されています。オブジェクトへのポインタとオブジェクトを持つことは、C++では全く異なった働きをします。

Hydeのようにオブジェクトをスライスします。正確にどこを混乱させるのかを知るのは難しいですが、さらに多くの研究がうまくいくでしょう。

BaseModelがNoteの基本クラスだとしますか?

場合: BaseModel modelを実行すると、ノートから初期化しても、ノートは作成されません。あなたは新しいBaseModelを作っています。これはキャストではなく、新しいものの創造です。 それはちょっと、このようなものだ:

int a; 
float b = a; 

bがint型ではない、それはそれはちょうどint型から初期化された、i​​nt型を指していません。それは "a"とは何の関係もないまったく新しいフロートです。

この行の後に、注(注)と完全に関係のないBaseModel(モデル)があります。

モデルをベクターに入れようとすると、コンパイラーは、BaseModelがノートではなく、Notesのベクトルを持っているため、これを実行できないことを正しく通知します。

あなたが正しい方向を指していることを願っています。

+0

特に、浮動小数点/比較の比較により明らかになりました。 –

5

C++の値は値です。これは多くの言語では当てはまりません。彼らは参照のみを使用するように強制します。

基底型にintが1つ含まれているとします。派生型に2が含まれています。派生型のインスタンスを基底に格納すると、2番目の整数のための空間はありません。

スライシングと呼ばれるものが発生します。導出された基底部分は基本値に格納されます。

データが破棄されたため、派生品に戻ることはできません。

これは実用的です。しかし、C++のモデルでは、型の値は型の型とまったく同じです。 dericed型が同じサイズであっても、base型の値に格納するとbase型の値が得られます。そこには派生オブジェクトはなく、常に基本オブジェクトです。

ポインタを使用すると、派生のインスタンスを指すポインタへのポインタは、派生したの部分を指しています。

バーチャルファンクションは、ベースオブジェクト内に埋め込まれた関数ポインタ(まあ、ポインタが埋め込まれている)の周りの構文的な砂糖です。派生インスタンスには、派生オーバーライドを使用するようにコーリングコードに指示する、別のものをポインターと仮想関数ポインターのポインターを結ぶ基本サブオブジェクトがあります。

これらのテーブルでは、チェックキャストが派生するま​​でのベースにすることもできます。

+0

ありがとう、それは意味があります。だから私は質問のような何かをしたい場合は、ポインタとポインタのベクトルを使用する唯一のソリューションですか? –

+1

@ this.lau_または参照。彼らも同様に動作します。しかし、あなたが参照のベクトルを持つことができるかどうかはわかりません。 –

+1

@ this.lau_解決方法のみ?いいえ、値型多型を含む何らかの奇妙な型削除を行うことができます。合理的な解決策のみ?はい。多態性が必要な場合は、 'vector'に' std :: unique_ptr 'を使用してください。要素の* copies *を作成する必要がある場合は、 'virtual std :: unique_ptr clone()const'メソッドを' Node'に追加し、子でオーバーライドしてください。 – Yakk

0

私はそれを逆にしていると思います。NoteBaseModelです。これは、逆が真であることを意味するものではない。

関連する問題