アプリ版:「スタンプのみでお礼する」機能のリリースについて

今までプログラム内で、設定データを格納するためのメモリの宣言として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に切り替えることが可能と思い込んでいたのですが、切り替えるにはどうしたらよいのかどうぞ、ご教示頂きますようお願い致します。

A 回答 (8件)

え?もしかして


http://oshiete.goo.ne.jp/qa/8688489.html
これって、派生クラスじゃなかったの?

多くの言語では、クラス同士の互換性が無いと、キャストしたりできません。
ですが、C言語のキャストはとても強力で、どんな型でも無理矢理に変換します。
特にポインタは、アドレスに続くデータをどう扱うかの違いだけなので、
m_pEnv = (env_t *)new env02_t;
としてもコンパイルエラーにはなりません。(動作時におかしくなるかもしれませんが)



C++の参考書、参考サイトで「クラスの継承」「アップキャスト」「仮想関数」とかいうあたりをよく勉強しましょう。



そもそも、最初からenv_tを書き換えてenv_02_t相当にしちゃだめなの?
    • good
    • 0
この回答へのお礼

回答頂きありがとうございます。

実は、

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でこのような表示になってしまうのかなどご教示頂けないでしょうか? よろしくお願い致します。

お礼日時:2014/07/23 22:13

なんか突っ込みたいところはありますが


ポインタの互換性があるのは継承されている場合のみです。


ケチらずに最初から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 )
{
// 対応するメンバ変数を全てコピーする処理
}
    • good
    • 0
この回答へのお礼

回答頂きありがとうございます。

Viewer側で

env_t *m_pEnv;


このように宣言していたポインターは


env_02_t *m_pEnv;


これで統一することにしました。


心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。

とりあえずこの設定で使用してみたいと思います。

助かります。

お礼日時:2014/07/31 19:16

そもそも


m_pEnv = (env_t *)new env02_t;
は「宣言」じゃないです.
    • good
    • 0
この回答へのお礼

回答頂きありがとうございます。

Viewer側で

env_t *m_pEnv;


このように宣言していたポインターは


env_02_t *m_pEnv;


これで統一することにしました。


心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。

とりあえずこの設定で使用してみたいと思います。

助かります。

お礼日時:2014/07/31 19:19

>このように宣言しているので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 と変わらないんだけど・・・

それとキャストが何の事かよくわかっていないようですから、ポインタを使いまくるのでしたらポインタとそのキャストについてはしっかり基本から学習された方がいいかと思います。
    • good
    • 0
この回答へのお礼

回答頂きありがとうございます。

Viewer側で

env_t *m_pEnv;


このように宣言していたポインターは


env_02_t *m_pEnv;


これで統一することにしました。


心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。

とりあえずこの設定で使用してみたいと思います。

助かります。

お礼日時:2014/07/31 19:16

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;
}
    • good
    • 0
この回答へのお礼

回答頂きありがとうございます。

Viewer側で

env_t *m_pEnv;


このように宣言していたポインターは


env_02_t *m_pEnv;


これで統一することにしました。


心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。

とりあえずこの設定で使用してみたいと思います。

助かります。

お礼日時:2014/07/31 19:19

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 のどちらかの適切なメンバ関数を勝手に呼んでくれます。
    • good
    • 0
この回答へのお礼

回答頂きありがとうございます。

Viewer側で

env_t *m_pEnv;


このように宣言していたポインターは


env_02_t *m_pEnv;


これで統一することにしました。


心配していた”env_t *m_pEnv;”これで動作している旧タイプの端末への設定データのアップロード、ダウンロードは設定が消えてしまうというような現象は起きていないことを確認しました。

とりあえずこの設定で使用してみたいと思います。

助かります。

お礼日時:2014/07/31 19:19

>”(env_t *)” キャスト? っていうことをやっているからenv02_tの型で設定したのにenv_tの型にm_pEnvが鳴ってしまったのだろうかと疑っています。



疑うも何も
m_pEnvの型は元からenv_t *なんでは・・・
m_pEnvの型がenv_t *なんですから、設定されているインスタンス(値)の型がenv02_t *であっても、そのままではenv_t *の情報しか参照できないです。
    • good
    • 0
この回答へのお礼

回答頂きありがとうございます。

お世話になっております。

このアプリケーションを起動した際に

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できないのですが、


型を宣言し直すということはできないと言うことなんでしょうか?


どうぞご教示頂きますようお願い致します。

お礼日時:2014/07/24 11:43

env_02_tはenv_tの派生クラスなんですか?

    • good
    • 0
この回答へのお礼

回答頂きありがとうございます。

実は、

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でこのような表示になってしまうのかなどご教示頂けないでしょうか? よろしくお願い致します。

お礼日時:2014/07/23 22:13

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!