- ベストアンサー
C++で変数の型を途中で切り替える方法
- C++で変数の型を途中で切り替える方法を教えてください。
- プログラム内で設定データを格納するためにenv_tという構造体を使っていましたが、途中で新しい構造体env_02_tに変える必要が生じました。構造体の切り替え方法を教えてください。
- env_tからenv_02_tに構造体を切り替える際にエラーが発生しています。エラーの原因と対処方法を教えてください。
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
え?もしかして http://okwave.jp/qa/q8688489.html これって、派生クラスじゃなかったの? 多くの言語では、クラス同士の互換性が無いと、キャストしたりできません。 ですが、C言語のキャストはとても強力で、どんな型でも無理矢理に変換します。 特にポインタは、アドレスに続くデータをどう扱うかの違いだけなので、 m_pEnv = (env_t *)new env02_t; としてもコンパイルエラーにはなりません。(動作時におかしくなるかもしれませんが) C++の参考書、参考サイトで「クラスの継承」「アップキャスト」「仮想関数」とかいうあたりをよく勉強しましょう。 そもそも、最初からenv_tを書き換えてenv_02_t相当にしちゃだめなの?
その他の回答 (7)
- syampoooooooooo
- ベストアンサー率44% (4/9)
なんか突っ込みたいところはありますが ポインタの互換性があるのは継承されている場合のみです。 ケチらずに最初からenv_02_t型を使うか、 env_02_t型を受け取るコンストラクタを実装してぶち込んでやるとか… バイト単位で完全な互換性がとれてるなら強引にキャストしても問題ない(プログラムの設計的には問題がある)と思います。 env_t *m_pEnv; ... env_02_t *m_p2Env = new env_02_t( m_pEnv ); delete m_pEnv; // 以後m_pEnvは使用禁止 ... // こんすとらくた env_02_t( env_t arg ) { // 対応するメンバ変数を全てコピーする処理 }
お礼
回答頂きありがとうございます。 Viewer側で env_t *m_pEnv; このように宣言していたポインターは env_02_t *m_pEnv; これで統一することにしました。 心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。 とりあえずこの設定で使用してみたいと思います。 助かります。
- Tacosan
- ベストアンサー率23% (3656/15482)
そもそも m_pEnv = (env_t *)new env02_t; は「宣言」じゃないです.
お礼
回答頂きありがとうございます。 Viewer側で env_t *m_pEnv; このように宣言していたポインターは env_02_t *m_pEnv; これで統一することにしました。 心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。 とりあえずこの設定で使用してみたいと思います。 助かります。
- wormhole
- ベストアンサー率28% (1626/5665)
>このように宣言しているのでm_pEnvの型はenv_tとなりますが、もし途中で型を変えたい場合には >delete m_pEnv; >として、 m_pEnvの値をdeleteしているのであってm_pEnvに何か作用があるわけじゃありません。 >新たに変更したい型として >m_pEnv = (env_t *)new env02_t; >このように宣言すれば型を”env02_t”にできると言うことにはならないのでしょうか? m_pEnvに(型がenv02_t *の)値を(型がenv_t *とコンパイラをだまして)設定しているだけであってm_pEnvの型が変わるわけじゃありません。 というかC,C++においては変数の型を動的に変えることはできません。 >このプログラムのやり方を入れてデバッグモードでm_pEnvをwatchしてみてもなぜかenv_tの型としてしかwatchできないのですが、 ですので「なぜか」ではなく、m_pEnvそのままではenv_t*としてしかwatchできないのは凄く当然の事です。 デバッガによってはwatchなどでキャスト可能なものもありますが、そういう機能がないのであればenv02_t *の変数に入れ直すなどして参照するしかないです。 # 書いてる内容 #3 と変わらないんだけど・・・ それとキャストが何の事かよくわかっていないようですから、ポインタを使いまくるのでしたらポインタとそのキャストについてはしっかり基本から学習された方がいいかと思います。
お礼
回答頂きありがとうございます。 Viewer側で env_t *m_pEnv; このように宣言していたポインターは env_02_t *m_pEnv; これで統一することにしました。 心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。 とりあえずこの設定で使用してみたいと思います。 助かります。
- tensor01
- ベストアンサー率0% (0/1)
C++における多態性は大体下記のように使います。まぁさわり程度の説明にすぎませんが。コード間違ってたらすいません。 class kuma_env_base { public: kuma_env(){} virtual ~kuma_env(){} }; class kuma_env_ : public kuma_env_base { kuma_env_(){} virtual ~kuma_env_(){} }; class kuma_env_2 : public kuma_env_base { kuma_env_2(){} virtual ~kuma_env_2(){} }; void check_type( kum_env_base *_p ) { kuma_env_ kuma = dynamic_cast<kuma_env_>(_p); kuma_env_2 kuma2 = dynamic_cast<kuma_env_2>(_p); if( kuma ) cout << "it's kuma_env_" << endl; if( kuma2 ) cout << "it's kuma_env_2" << endl; } int main() { kuma_env_base *p = new kuma_env_; kuma_env_base *p2 = new kuma_env_2; check_type(p); check_type(p2); return 0; }
お礼
回答頂きありがとうございます。 Viewer側で env_t *m_pEnv; このように宣言していたポインターは env_02_t *m_pEnv; これで統一することにしました。 心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。 とりあえずこの設定で使用してみたいと思います。 助かります。
- 麻野 なぎ(@asano_nagi)
- ベストアンサー率35% (42/120)
C++では、構造体も(文法上)クラスなので struct evn_t { .... ここに、必要なデータを並べる virtual void upload(std::ifstream otf); // ファイルとか、アップロードをする相手を引数とするメンバ関数を作る // 仮想関数として作成 }; これを継承した、env02_t を struct env02_t : public evn_t { ... ここに追加データを並べる virtual void upload(* std::ifstream otf); // 同じように、env02_t 型のデータをアップロードするメンバ関数を作る }; ここで、 struct env_t *m_pEnv; というm_pEnv に対して、 m_Env = new env_t; n_Env = new env02_t; は共に正しいです。 また、 m_Env->upload(otf); などで、m_Env に入っている、env_t か、env02_t のどちらかの適切なメンバ関数を勝手に呼んでくれます。
お礼
回答頂きありがとうございます。 Viewer側で env_t *m_pEnv; このように宣言していたポインターは env_02_t *m_pEnv; これで統一することにしました。 心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。 とりあえずこの設定で使用してみたいと思います。 助かります。
- wormhole
- ベストアンサー率28% (1626/5665)
>”(env_t *)” キャスト? っていうことをやっているからenv02_tの型で設定したのにenv_tの型にm_pEnvが鳴ってしまったのだろうかと疑っています。 疑うも何も m_pEnvの型は元からenv_t *なんでは・・・ m_pEnvの型がenv_t *なんですから、設定されているインスタンス(値)の型がenv02_t *であっても、そのままではenv_t *の情報しか参照できないです。
お礼
回答頂きありがとうございます。 お世話になっております。 このアプリケーションを起動した際に env_t * m_pEnv; このように宣言しているのでm_pEnvの型はenv_tとなりますが、もし途中で型を変えたい場合には delete m_pEnv; として、 新たに変更したい型として m_pEnv = (env_t *)new env02_t; このように宣言すれば型を”env02_t”にできると言うことにはならないのでしょうか? このプログラムのやり方を入れてデバッグモードでm_pEnvをwatchしてみてもなぜかenv_tの型としてしかwatchできないのですが、 型を宣言し直すということはできないと言うことなんでしょうか? どうぞご教示頂きますようお願い致します。
- wormhole
- ベストアンサー率28% (1626/5665)
env_02_tはenv_tの派生クラスなんですか?
お礼
回答頂きありがとうございます。 実は、 http://oshiete.goo.ne.jp/qa/8688489.html こちらの内容のことで相談させて頂きました。お気付き頂き感謝します。 元々は env_t * m_pEnv これだったものを、特定の端末に接続した場合は、 m_pEnv = (env_t *)new env02_t; こちらに変換したいという目的でやっていて実際これでデバッグモードで動作差せてみたところ、 なぜか、 m_pEnv = (env_t *)new env02_t; これで型を変換したはずなのに、なぜかデバッグでブレイクをかけてm_pEnvのデータ内容をwatchしてみたところ、なぜかenv_tの型でenv_tの後ろに追加した30バイト分のデータ部分が表示できていないことがわかりました。 それで、プログラムを見直し m_pEnv = (env_t *)new env02_t; ”(env_t *)” キャスト? っていうことをやっているからenv02_tの型で設定したのにenv_tの型にm_pEnvが鳴ってしまったのだろうかと疑っています。 なぜデバッグのwatchでこのような表示になってしまうのかなどご教示頂けないでしょうか? よろしくお願い致します。
お礼
回答頂きありがとうございます。 実は、 http://oshiete.goo.ne.jp/qa/8688489.html こちらの内容のことで相談させて頂きました。お気付き頂き感謝します。 元々は env_t * m_pEnv これだったものを、特定の端末に接続した場合は、 m_pEnv = (env_t *)new env02_t; こちらに変換したいという目的でやっていて実際これでデバッグモードで動作差せてみたところ、 なぜか、 m_pEnv = (env_t *)new env02_t; これで型を変換したはずなのに、なぜかデバッグでブレイクをかけてm_pEnvのデータ内容をwatchしてみたところ、なぜかenv_tの型でenv_tの後ろに追加した30バイト分のデータ部分が表示できていないことがわかりました。 それで、プログラムを見直し m_pEnv = (env_t *)new env02_t; ”(env_t *)” キャスト? っていうことをやっているからenv02_tの型で設定したのにenv_tの型にm_pEnvが鳴ってしまったのだろうかと疑っています。 なぜデバッグのwatchでこのような表示になってしまうのかなどご教示頂けないでしょうか? よろしくお願い致します。