トップ回答者
構造体とスコープ

質問
-
毎度お世話になります
構造体を使ってみたらハマリましたので質問させてください。
プロジェクトのnamespaceの直下で構造体を宣言し、namespaceの中のFom1周りで実体化を行いました。大体
以下のようなイメージです。
namespace Malchut {using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;//エクセル名前空間の使用
using namespace Excel;//オリジナル構造体
public ref struct sttest{
String^ hogehoge;
};/// <summary>
/// Form1 の概要
///
/// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた
/// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを
/// 変更する必要があります。この変更を行わないと、
/// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、
/// 正しく相互に利用できなくなります。
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
//オリジナルクラステスト
public:
//クラスは配列に出来ないらしい
//array<Hyodai^>^ h1;
Hyodai^ h1;
public:
Form1(void)
{
InitializeComponent();//オリジナルクラステスト
//h1 = gcnew array<Hyodai()>(500);
h1 = gcnew Hyodai();//オリジナル構造体実体化テスト
sttest^ kozo_test = gcnew sttest();
いろいろと突っ込みはあろうかと思いますが、ここまではコンパイラにも怒られず、うまくいきました。
これで構造体kozo_testが実体化したはずなのですが、Form1上のボタンのクリックイベントにて構造体を参照しようとすると
エラーになります。というよりも、コード補完で構造体名が出てきません。コードは以下のようなイメージです。
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
kozo_test->hogehoge = "ほえほえ"; //これはエラー
}
ボタンのクリックイベント中で構造体の実体化を行うと、上のコードはすんなり動きます。
私としては複数のボタンクリックイベントで構造体のグローバル変数を共有したいと思っています。それで「//オリジナル構造体実体化テスト」
のあたりで構造体を実体化したのですが動いてくれません。
それで今回の質問としては構造体の使い方とグローバル変数の使い方がわからないというイメージです。今作ってるプログラムはフォームが一個
しかないのですが、フォームが複数になった場合グローバル変数が使えないと不便しそうです。
よろしくお願いします。
回答
-
kozo_test は Form1 のコンストラクタのローカル変数ですから、そりゃあ他のメソッドから参照することはできないと思いますが。
他のメソッドから参照したいならメンバ変数にしないと。//クラスは配列に出来ないらしい
そんなことはありません。
//array<Hyodai^>^ h1;グローバル変数を共有したい
グローバル変数にする意味は無さそうです。メンバ変数で十分。
正直、いきなり C++/CLI に手を出すのはハードルが高すぎるレベルに見えます。
C# とかでオブジェクト指向の基本から勉強するのをお勧めします。というかむしろそうすべきです。- 回答としてマーク 高橋 春樹 2010年3月24日 6:33
-
大筋は既に回答が出ているので、もう一点だけ。
今作ってるプログラムはフォームが一個しかないのですが、フォームが複数になった場合グローバル変数が使えないと不便しそうです。
そうでもないです。
適切に設計・実装すれば、なんとかなります。
逆に、グローバル変数だといつ、どこからでも書き換えられるので不具合を探すのが大変です。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク 高橋 春樹 2010年3月24日 6:32
-
お世話になってます。
というわけで、ごにょごにょとトライ&エラーを繰り返した結果、問題は解決しました。といっても、なんとなく動くって
だけなんですが・・・・
以下、やったことを記述します。
①ヘッダファイルをプロジェクトに追加。hyojunmodule.hとしました
②hyojunmodule.hに以下のように記述
#pragma oncenamespace Malchut {
using namespace System;
//ウリジナル構造体
//public ref struct sttest2{
// String^ hoehoe;
//};public ref struct sttest{
String^ hogehoge;
//sttest2^ kozo2; これは実体化しない
//入れ子はこうするしかないっぽい
ref struct sttest2{
String^ hoehoe;
}kozo2;
};}
③Form1.hにインクルード文を書く
include "hyojunmodule.h"
④とりあえず、構造体の宣言だけ
public ref class Form1 : public System::Windows::Forms::Form
{
//ウリジナル構造体宣言
sttest^ kozo_test; // = gcnew sttest(); ここでは実体化できないっぽい
⑤Form1のコントラクタで実体化
Form1(void)
{
InitializeComponent();//ウリジナル構造体実体化テスト
kozo_test = gcnew sttest();
⑥ボタン1のクリックイベントを記述
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
//ウリジナルクラステスト
//kozo_test->kozo2->hoehoe = "ほえほえ"; なにやらオペラントが違うらしい
kozo_test->kozo2.hoehoe = "ほえほえ";kozo_test->hogehoge = "ほげほげ"; //これは->でいいらしい
⑦ボタン2のクリックイベントを記述
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
MessageBox::Show(kozo_test->kozo2.hoehoe);
以上のコードでボタン1クリックでデータを取得して、ボタン2クリックでメッセージボックスに「ほえほえ」を
出力することが出来ました。
こちらとしては、なんとか「グローバル変数のようなもの」を確保した感じです。- 回答としてマーク 高橋 春樹 2010年3月24日 6:33
-
こちらとしては、なんとか「グローバル変数のようなもの」を確保した感じです。
それはグローバル変数ではなく、メンバー変数と呼ばれるものです。
Form1 というクラスの同じインスタンスの間で共有される変数です。
Form2, Form3 とクラスを増やしたときの別のクラスとの間や、Form1 クラスのインスタンスを複数作ったときのインスタンス間では共有されません。
クラスとは何か、メンバー変数とは何かといった基礎的なことをまず学んでください。
# 個人的にはいきなり C++/CLI はハードルが高いという意見に同感ですが。。。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク 高橋 春樹 2010年3月24日 6:33
-
外池と申します。横から口出しして申し訳ありません。
>>クラスとは何か、メンバー変数とは何かといった基礎的なことをまず学んでください。
>みなさんそう仰いますが、この辺の資料って意外とないです。表面的な使い方を
>書いてる本は結構あるイメージですが、動作原理とかそいうのを解説してる本は
>今のところ見つかりません。
いやー、資料、いっぱいあると思いますよ? (「C++/CLIはハードルが高い」は理由が別のところにあると思うので横においておいて)、単に「クラス」とか「メンバー」とかだけに限れば、本の種類として2種類あると思います。
-----------
まずは、C++の本で、オブジェクト指向プログラミング(OOP)の解説をした本を探してみてください。これは非常に沢山出ています。C言語がわかる、ということであれば、CからC++への移行を想定したような本が便利かと思います。例えば、私の手元にあるのは、
C++:オブジェクト指向プログラミング
R.S.ウィナー/L.J.ピンソン著 前川守訳
ISBN4-8101-8009-3
です。私が最初にこれを読んだのは、まだ、.Net Frameworkが出る前だったと記憶しています。当時C++でWindowアプリを作るのは私にはハードルが高すぎて、Visual Basicで作っていましたが、VB5やVB6の「クラス」の機能はえらく中途半端で本に書かれた概念のごく一部しか実践できませんでした。その後、.Net Frameworkが出て、VB.NETやC#で、本格的にOOPが可能になり、かつ、大変楽にWindowアプリが作れるようになりました。
-----------
で、あともうひとつの種類の本として、C#の本です。これも最近沢山出てきました。一応、C#の言語仕様としての「クラス」や「メンバー」の定義は必ず載っています。
ただ、私が感じるところ、C#でOOPの概念や考え方を解説したものは少ないように思います。C#の言語仕様のリファレンス・ブックの類がほとんどでしょうか。これは、まぁ、C++とC#の歴史の違いからして、しょうがないとは思いますが。
-----------
C++/CLIがハードルが高いということに関してですが、言語仕様が非常に難解というわけではないと思います。ただ、素のC++っぽい部分(いわゆるアンマネージ)と、.Net Frameworkの仕組みで動く部分(マネージ)を常に意識しながらプログラムを書かないといけない面倒さ、あとその区別の文法上のお作法にすごく疲れる、というところで、
両者をチャンポンにする必要がない限り、アンマネージだけでプログラムできるならC++(CLIの機能は切る。)、マネージだけでプログラムできるならC#、というように割り切ったほうが、学習も実作業もはるかに効率が上がると思います。
ちなみに、OOPについてC++の本を読みつつ、C#でプログラムを書いて動作確認してみることも、十分に可能です。
(ホームページを再開しました)- 回答としてマーク 高橋 春樹 2010年3月24日 6:33
-
要するにクラスの概念をきちんと理解する事とC++/CLIに関する文法書を使ってきちんと言語の文法を勉強する事が必要です。
この辺の文法やクラスの概念に関しては結局は書籍できちんと勉強するしか有りません。
あくまでも概念の部分の理解になりますから。
手元に一冊本が有りますので一応紹介しておきます。
実践 C++/CLI 極めるための基礎と実用テクニック
Softbank Creative
ただし、この本はC++言語のクラスの概念がある程度ある事を前提にしている模様です。
できれば、C++言語の入門書でクラスの概念や文法について体系的に勉強される事をお勧めします。
今まで経験してきた言語に関しては一旦忘れた方が良いかもしれません。
アルゴリズムの部分は応用で来ても文法の部分に関しては言語毎に違いがありますから
反って他の言語の知識が邪魔になるケースもありえますよ。
追伸:
前にも書きましたが、C++/CLI言語とC++言語は別物です。
ですが、クラスの概念等に関しては同様の部分があります。
C++/CLI言語の本にその部分の記述が無いのであれば、C++言語の本などでその部分の知識を補完する必要があります。
また、この部分の概念がわからないと基本的にC++言語もC++/CLI言語も使いこなせ無いと思った方が良いです。
そういう意味では、C++/CLIはいきなり勉強するにはやりにくい言語と言う事は言えると思います。
C++言語とC++/CLI言語を比べてC++/CLI言語の方が難しいという意味ではなくて勉強する環境を見た時にめんどくさいと言う意味です。
C++/CLIに関してはネイティブと.NET の架け橋的な使い方がメインでこれのみでアプリを構築すると言うのは考えにくいと思っているので
C++言語なりの知識が無いのにC++/CLIだけ勉強してもあまり活躍できないのではないかなぁと言うのが個人的な意見ですね。
解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。 -
C++/CLI は C++ である程度書けることと、.NET の知識を要求されることという点はすでに書かれていますが、私も同じ見解です。
初歩として取り組むには、段階を踏むべきです。
(ハードルが高いまま挑むのではなく、土台を積み上げるべき)手元に一冊本が有りますので一応紹介しておきます。
実践 C++/CLI 極めるための基礎と実用テクニック
Softbank Creative残念ながら、こちらの書籍はすでに購入できません。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク 高橋 春樹 2010年3月24日 6:33
すべての返信
-
kozo_test は Form1 のコンストラクタのローカル変数ですから、そりゃあ他のメソッドから参照することはできないと思いますが。
他のメソッドから参照したいならメンバ変数にしないと。//クラスは配列に出来ないらしい
そんなことはありません。
//array<Hyodai^>^ h1;グローバル変数を共有したい
グローバル変数にする意味は無さそうです。メンバ変数で十分。
正直、いきなり C++/CLI に手を出すのはハードルが高すぎるレベルに見えます。
C# とかでオブジェクト指向の基本から勉強するのをお勧めします。というかむしろそうすべきです。- 回答としてマーク 高橋 春樹 2010年3月24日 6:33
-
大筋は既に回答が出ているので、もう一点だけ。
今作ってるプログラムはフォームが一個しかないのですが、フォームが複数になった場合グローバル変数が使えないと不便しそうです。
そうでもないです。
適切に設計・実装すれば、なんとかなります。
逆に、グローバル変数だといつ、どこからでも書き換えられるので不具合を探すのが大変です。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク 高橋 春樹 2010年3月24日 6:32
-
お世話になってます。
というわけで、ごにょごにょとトライ&エラーを繰り返した結果、問題は解決しました。といっても、なんとなく動くって
だけなんですが・・・・
以下、やったことを記述します。
①ヘッダファイルをプロジェクトに追加。hyojunmodule.hとしました
②hyojunmodule.hに以下のように記述
#pragma oncenamespace Malchut {
using namespace System;
//ウリジナル構造体
//public ref struct sttest2{
// String^ hoehoe;
//};public ref struct sttest{
String^ hogehoge;
//sttest2^ kozo2; これは実体化しない
//入れ子はこうするしかないっぽい
ref struct sttest2{
String^ hoehoe;
}kozo2;
};}
③Form1.hにインクルード文を書く
include "hyojunmodule.h"
④とりあえず、構造体の宣言だけ
public ref class Form1 : public System::Windows::Forms::Form
{
//ウリジナル構造体宣言
sttest^ kozo_test; // = gcnew sttest(); ここでは実体化できないっぽい
⑤Form1のコントラクタで実体化
Form1(void)
{
InitializeComponent();//ウリジナル構造体実体化テスト
kozo_test = gcnew sttest();
⑥ボタン1のクリックイベントを記述
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
//ウリジナルクラステスト
//kozo_test->kozo2->hoehoe = "ほえほえ"; なにやらオペラントが違うらしい
kozo_test->kozo2.hoehoe = "ほえほえ";kozo_test->hogehoge = "ほげほげ"; //これは->でいいらしい
⑦ボタン2のクリックイベントを記述
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
MessageBox::Show(kozo_test->kozo2.hoehoe);
以上のコードでボタン1クリックでデータを取得して、ボタン2クリックでメッセージボックスに「ほえほえ」を
出力することが出来ました。
こちらとしては、なんとか「グローバル変数のようなもの」を確保した感じです。- 回答としてマーク 高橋 春樹 2010年3月24日 6:33
-
こちらとしては、なんとか「グローバル変数のようなもの」を確保した感じです。
それはグローバル変数ではなく、メンバー変数と呼ばれるものです。
Form1 というクラスの同じインスタンスの間で共有される変数です。
Form2, Form3 とクラスを増やしたときの別のクラスとの間や、Form1 クラスのインスタンスを複数作ったときのインスタンス間では共有されません。
クラスとは何か、メンバー変数とは何かといった基礎的なことをまず学んでください。
# 個人的にはいきなり C++/CLI はハードルが高いという意見に同感ですが。。。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク 高橋 春樹 2010年3月24日 6:33
-
毎度お世話になってます。
引用のしかたがイマイチわからないので、原始的な方法で失礼しま。
>Form2, Form3 とクラスを増やしたときの別のクラスとの間や、Form1 クラスのインスタンスを複数作ったときのインスタンス間では共有されません。
namespaceの階層から私もそう思いました。Fom1クラスの外で変数を宣言しようとしたのですが、コンパイラに「マネージ型がうんぬん」
とか怒られます。ということは、アンマネージならOKなのか??? などと考えてますが、まだ調べてません。
>クラスとは何か、メンバー変数とは何かといった基礎的なことをまず学んでください。
みなさんそう仰いますが、この辺の資料って意外とないです。表面的な使い方を書いてる本は結構あるイメージですが、動作原理とか
そいうのを解説してる本は今のところ見つかりません。
http://ec.nikkeibp.co.jp/item/books/A06000.html
良さそうと思って昨日買ってみたんですけど、これもどうですかねぇ。ヒマを見て読んでみようと思います。
>個人的にはいきなり C++/CLI はハードルが高いという意見に同感ですが。。。
これもみなさんそう仰いますが、これを言い出したら永久にハードルが高いままってことですよね???
昨日思い出したのですが、私大昔にQuickCを弄ってました。よって普通のC言語もちょっぴりならわかります。開発の効率とかは
あんまり考えなくていい立場ですので、もう少しC++/CLIで粘ってみようと思います。
> -
外池と申します。横から口出しして申し訳ありません。
>>クラスとは何か、メンバー変数とは何かといった基礎的なことをまず学んでください。
>みなさんそう仰いますが、この辺の資料って意外とないです。表面的な使い方を
>書いてる本は結構あるイメージですが、動作原理とかそいうのを解説してる本は
>今のところ見つかりません。
いやー、資料、いっぱいあると思いますよ? (「C++/CLIはハードルが高い」は理由が別のところにあると思うので横においておいて)、単に「クラス」とか「メンバー」とかだけに限れば、本の種類として2種類あると思います。
-----------
まずは、C++の本で、オブジェクト指向プログラミング(OOP)の解説をした本を探してみてください。これは非常に沢山出ています。C言語がわかる、ということであれば、CからC++への移行を想定したような本が便利かと思います。例えば、私の手元にあるのは、
C++:オブジェクト指向プログラミング
R.S.ウィナー/L.J.ピンソン著 前川守訳
ISBN4-8101-8009-3
です。私が最初にこれを読んだのは、まだ、.Net Frameworkが出る前だったと記憶しています。当時C++でWindowアプリを作るのは私にはハードルが高すぎて、Visual Basicで作っていましたが、VB5やVB6の「クラス」の機能はえらく中途半端で本に書かれた概念のごく一部しか実践できませんでした。その後、.Net Frameworkが出て、VB.NETやC#で、本格的にOOPが可能になり、かつ、大変楽にWindowアプリが作れるようになりました。
-----------
で、あともうひとつの種類の本として、C#の本です。これも最近沢山出てきました。一応、C#の言語仕様としての「クラス」や「メンバー」の定義は必ず載っています。
ただ、私が感じるところ、C#でOOPの概念や考え方を解説したものは少ないように思います。C#の言語仕様のリファレンス・ブックの類がほとんどでしょうか。これは、まぁ、C++とC#の歴史の違いからして、しょうがないとは思いますが。
-----------
C++/CLIがハードルが高いということに関してですが、言語仕様が非常に難解というわけではないと思います。ただ、素のC++っぽい部分(いわゆるアンマネージ)と、.Net Frameworkの仕組みで動く部分(マネージ)を常に意識しながらプログラムを書かないといけない面倒さ、あとその区別の文法上のお作法にすごく疲れる、というところで、
両者をチャンポンにする必要がない限り、アンマネージだけでプログラムできるならC++(CLIの機能は切る。)、マネージだけでプログラムできるならC#、というように割り切ったほうが、学習も実作業もはるかに効率が上がると思います。
ちなみに、OOPについてC++の本を読みつつ、C#でプログラムを書いて動作確認してみることも、十分に可能です。
(ホームページを再開しました)- 回答としてマーク 高橋 春樹 2010年3月24日 6:33
-
毎度お世話になってます。
>C++:オブジェクト指向プログラミング
R.S.ウィナー/L.J.ピンソン著 前川守訳
ISBN4-8101-8009-3
http://www.amazon.co.jp/C-%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E3%82%A2%E3%82%B8%E3%82%BD%E3%83%B3-%E3%82%A6%E3%82%A7%E3%82%B9%E3%83%AC%E3%82%A4%E3%83%BB%E3%83%88%E3%83%83%E3%83%91%E3%83%B3%E6%83%85%E5%A0%B1%E7%A7%91%E5%AD%A6%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-R-S-%E3%82%A6%E3%82%A4%E3%83%8A%E3%83%BC/dp/4810180093
本のご紹介ありがとうございます。
でも、なにやらすでに絶版みたいです。まぁその、私は外人翻訳物が苦手(オライリーとかもダメです)ですし、金も
ないのでとりあえず自分で買った本から読んでみようと思います。
ありがとうございました。 -
要するにクラスの概念をきちんと理解する事とC++/CLIに関する文法書を使ってきちんと言語の文法を勉強する事が必要です。
この辺の文法やクラスの概念に関しては結局は書籍できちんと勉強するしか有りません。
あくまでも概念の部分の理解になりますから。
手元に一冊本が有りますので一応紹介しておきます。
実践 C++/CLI 極めるための基礎と実用テクニック
Softbank Creative
ただし、この本はC++言語のクラスの概念がある程度ある事を前提にしている模様です。
できれば、C++言語の入門書でクラスの概念や文法について体系的に勉強される事をお勧めします。
今まで経験してきた言語に関しては一旦忘れた方が良いかもしれません。
アルゴリズムの部分は応用で来ても文法の部分に関しては言語毎に違いがありますから
反って他の言語の知識が邪魔になるケースもありえますよ。
追伸:
前にも書きましたが、C++/CLI言語とC++言語は別物です。
ですが、クラスの概念等に関しては同様の部分があります。
C++/CLI言語の本にその部分の記述が無いのであれば、C++言語の本などでその部分の知識を補完する必要があります。
また、この部分の概念がわからないと基本的にC++言語もC++/CLI言語も使いこなせ無いと思った方が良いです。
そういう意味では、C++/CLIはいきなり勉強するにはやりにくい言語と言う事は言えると思います。
C++言語とC++/CLI言語を比べてC++/CLI言語の方が難しいという意味ではなくて勉強する環境を見た時にめんどくさいと言う意味です。
C++/CLIに関してはネイティブと.NET の架け橋的な使い方がメインでこれのみでアプリを構築すると言うのは考えにくいと思っているので
C++言語なりの知識が無いのにC++/CLIだけ勉強してもあまり活躍できないのではないかなぁと言うのが個人的な意見ですね。
解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。 -
C++/CLI は C++ である程度書けることと、.NET の知識を要求されることという点はすでに書かれていますが、私も同じ見解です。
初歩として取り組むには、段階を踏むべきです。
(ハードルが高いまま挑むのではなく、土台を積み上げるべき)手元に一冊本が有りますので一応紹介しておきます。
実践 C++/CLI 極めるための基礎と実用テクニック
Softbank Creative残念ながら、こちらの書籍はすでに購入できません。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク 高橋 春樹 2010年3月24日 6:33