こんにちは。WindowsXP Home VisualC++.net 2003を使っています。
質問があります。フォームにボタンを用意して(この例では5個目)そこにコードを書
いてビルドエラーもなく、実行してみると、こんなメッセージが出ました。
「System.NullReference Exceptionのハンドルされていない例外が発生しました。オブ
ジェクト参照がオブジェクトインスタンスに設定されていません」
原因を探るためにコードを削っていくとこの配列の「ここ」の部分らしいのですが、自
分には何がいけないのか検討もつきません。もちろんビルドエラーもないんですけど…
ほかのコントロールやクラスの定義は変えてはいないので、このボタンコントロールを
加えたことが原因だと思うんですけど、どなたか何か分かりますか?
Debug::WriteLine()はテスト用に用意したものです。
private: System::Void button5_Click(System::Object * sender,
System::EventArgs * e)
{
String* moji[];
moji[0] = A;
moji[1] = B; //←ここ
moji[2] = C;
moji[3] = D;
moji[4] = E;
moji[5] = 休;
moji[6] = 休;
//コードはコメントアウトしてある
Debug::WriteLine(moji[0]);
}
変数mojiの領域が確保されていないからです。
moji[6]までしか使わないと決まっているのなら
String *moji[7];
と宣言して下さい。サイズが実行時まで決まらないのなら newで領域を確保します。
moji[7]とやってみると今度はビルドエラーで、
「__gc 配列宣言でサイズを指定できません」
と出てしまいます。自分も初めはそれだと思ったんですけど…String* の場合はポイン
タだからですかね?
初心者なので new での領域確保を具体的に教えていただけますか?
C# と同じでいいのなら…
String* moji[] = __gcnew String*[7];
とかかなぁ。
ごめん __gcnew なんてなかった。
Managed C++ ではどう書くんだっけ…?
> Managed C++ ではどう書くんだっけ…?
System::String* moji __gc[] = __gc new System::String* __gc[ 7 ];
ですね。
ちなみに、
> サイズが実行時まで決まらないのなら
ときは System::Collections::ArrayList を使います。
使用例)
System::Collections::ArrayList* planets = __gc new
System::Collections::ArrayList();
planets->Add( SMercury );
planets->Add( SVenus );
planets->Add( SEarth );
planets->Add( SMars );
planets->Add( SJupiter );
planets->Add( SSaturn );
planets->Add( SUranus );
planets->Add( SNeptune );
planets->Add( SPluto );
for ( int i = 0; i < planets->Count; i++ )
{
System::Console::WriteLine( S{0}:{1}, __box( i + 1 ), planets->Item[
i ] );
}
String* moji[]; と書くとCStringのポインタの配列になってしまうので、*は、必要な
いですよ。
CString moji[] ={A, B, C, D, E, 休, 休};
又は、CString moji[] ={ABCDE休休};でいいと思います。
もし new を使うのでしたら、
CString* moji;
moji = new CString[n]; // n : 配列数
moji[0] = A;
…
// 処理
delete[] moji;
でいいと思います。
> さささん
質問は Managed C++ についてです。
MFCではありません。
> String* moji[]; と書くとCStringのポインタの配列になってしまうので、*は、必要な
> いですよ。
String *ですから,System::String *の配列になります。
CStringとは関係ありません。
MFCではなく,.NET Frameworkの話ですから,
String* moji[]
でよいです。
ごめんなさい追加です。
配列数の n は処理中に変えることができますよ。n を変数として宣言しても実行できま
す。
CString* moji;
int n = 7;
moji = new CString[n]; // n : 配列数
…
> String* moji[]
> でよいです。
ではダメなのでは?
String* moji __gc[];
のようにしてマネージドクラスの配列(これもマネージド)というふうにしないと。
> String* moji[]
あれ?これでもコンパイル通るのですね。
どのような扱いになっているんでしょう。。。
すいませんでした。
String* moji[];
と
String* moji __gc[];
一緒なんですね。newするときだけが特殊なのですね。
# __gc を省略できる(?)ときが微妙にわからない。
連続になってすいません。
> # __gc を省略できる(?)ときが微妙にわからない。
で、
> System::String* moji __gc[] = __gc new System::String* __gc[ 7 ];
の__gcはいくつ省略できるか試してみたところ、
全部できましたw
よって、シャノンさんの
> String* moji[] = __gcnew String*[7];
がニアピンだったのですね。
String* moji[] = new String*[ 7 ];