今までプログラム内で、設定データを格納するためのメモリの宣言としてenv_tという構造体を使って
env_t *m_pEnv;
この宣言を行っていたのですが、プログラム途中でenv_tの構造体に+30バイト程度追加しなければならない箇所が出たため新たにenv_02_tという構造体を作成しました。
その構造体を使わなくてはならない分岐に来たら
delete m_pEnv;
として、
m_pEnv = new env_02_t;
と行ったところ、次のようなエラーが発生しました。
[BCC32 Error] uMain.cpp(2801): E2034 Cannot convert '_KUMA_ENV_02_ *' to '_KUMA_ENV_ *'
てっきりこれで構造体をenv_tからenv_02_tに切り替えることが可能と思い込んでいたのですが、切り替えるにはどうしたらよいのかどうぞ、ご教示頂きますようお願い致します。
No.2ベストアンサー
- 回答日時:
え?もしかして
http://oshiete.goo.ne.jp/qa/8688489.html
これって、派生クラスじゃなかったの?
多くの言語では、クラス同士の互換性が無いと、キャストしたりできません。
ですが、C言語のキャストはとても強力で、どんな型でも無理矢理に変換します。
特にポインタは、アドレスに続くデータをどう扱うかの違いだけなので、
m_pEnv = (env_t *)new env02_t;
としてもコンパイルエラーにはなりません。(動作時におかしくなるかもしれませんが)
C++の参考書、参考サイトで「クラスの継承」「アップキャスト」「仮想関数」とかいうあたりをよく勉強しましょう。
そもそも、最初からenv_tを書き換えてenv_02_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でこのような表示になってしまうのかなどご教示頂けないでしょうか? よろしくお願い致します。
No.8
- 回答日時:
なんか突っ込みたいところはありますが
ポインタの互換性があるのは継承されている場合のみです。
ケチらずに最初から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;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。
とりあえずこの設定で使用してみたいと思います。
助かります。
No.7
- 回答日時:
そもそも
m_pEnv = (env_t *)new env02_t;
は「宣言」じゃないです.
回答頂きありがとうございます。
Viewer側で
env_t *m_pEnv;
このように宣言していたポインターは
env_02_t *m_pEnv;
これで統一することにしました。
心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。
とりあえずこの設定で使用してみたいと思います。
助かります。
No.6
- 回答日時:
>このように宣言しているので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;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。
とりあえずこの設定で使用してみたいと思います。
助かります。
No.5
- 回答日時:
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;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。
とりあえずこの設定で使用してみたいと思います。
助かります。
No.4
- 回答日時:
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;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。
とりあえずこの設定で使用してみたいと思います。
助かります。
No.3
- 回答日時:
>”(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できないのですが、
型を宣言し直すということはできないと言うことなんでしょうか?
どうぞご教示頂きますようお願い致します。
No.1
- 回答日時:
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でこのような表示になってしまうのかなどご教示頂けないでしょうか? よろしくお願い致します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Perl Perlのエラーについてご教授ください。初心者です。 CGIを別サーバに移したところ、Perlのバー 5 2023/05/31 10:48
- その他(プログラミング・Web制作) ラズパイ上の、pythonのエラーについて 1 2023/04/12 23:27
- CGI -T(汚染モード)でメールが送れません 1 2022/06/12 14:11
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- その他(IT・Webサービス) ホームページにカウント数を表示する 2 2022/10/28 10:37
- C言語・C++・C# C言語 2 2022/07/21 00:02
- 英語 提示文の構造について(名詞+be that V?) 2 2023/05/19 09:46
- C言語・C++・C# プログラムが書けません。 4 2023/01/22 22:57
- モニター・ディスプレイ フルHD6枚表示できるPCの最適構成は何でしょうか? 4 2022/11/18 19:07
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
セグメントエラー
-
戻り値で構造体を返すことは可...
-
fopne で失敗する原因
-
init関数の意味
-
ExcelVBAでのkernel32(64bit)
-
Run-Time Check Failure #3とい...
-
NULLとブランクの違い
-
関数ポインタの高速化のメリット
-
Cで作成したDLL関数をVBから呼...
-
main(int argc,char **argv[])...
-
LPSTR型の初期化について
-
C言語のポインタに直接アドレス...
-
アプリを32bitから64bit移行
-
ハンドル、アドレス、ポインタ...
-
CWnd::EnableWindow()の扱い方
-
#define NULL ((void *)0) の弊害
-
C言語でのconstを返す関数
-
C言語の関数と配列に関する質問
-
C++で関数ポインタから関数名を...
-
関数ポインタの利点
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
C言語の関数と配列に関する質問
-
戻り値で構造体を返すことは可...
-
fopne で失敗する原因
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
LPSTR型の初期化について
-
セグメントエラー
-
アプリを32bitから64bit移行
-
コンストラクタでnewを失敗した...
-
ExcelVBAでのkernel32(64bit)
-
Cで作成したDLL関数をVBから呼...
-
ハンドルはポインタか
-
DLL<->VB間での受け渡し(文字...
-
C言語でのconstを返す関数
-
ポインタについて
-
参照型で受け取った引数をポイ...
-
TCHAR文字列内の検索について
-
デバイスハンドルとは?
-
基本アルゴリズムの『返す』の...
おすすめ情報