落穂拾い(これまでに出た質問とか)

1月17日辺り 授業内容

今日やったこと

   (newでインスタンスを動的に生成する方法)

   と、その初期化法(コンストラクタ呼んで初期化するんだよ)

クラスへのポインター?

授業の時に、以下の単語が入り乱れていてわかりづらかったかもしれません。

クラスへのポインタと話していたのは、
クラスのインスタンスへのポインタ = あるクラスのインスタンスとして作られたオブジェクトへのポインタ
です。
つまり、

#include <iostream>
 
class cMe{
	public:
	int m_age;
};
 
int main() {
  cMe watashi; //cMe型の変数(=クラスのインスタンス=cMeオブジェクト)
  cMe *p=nullptr; //cMe型のインスタンスへのポインタ
 
  p = &watashi; //これは、どういう意味か説明できればOK
 
  return 0;
}

オブジェクト配列

次に、オブジェクト配列ってのが引っ掛かった人が何人かいるみたい。
オブジェクト=インスタンス=クラスから作られた実際の変数だったね。
じゃぁ、結局、そのクラス型の変数の配列だよね。

#include <iostream>
 
class cMe{
	public:
	int m_age;
};
 
int main() {
  cMe watashi; 
  //cMe型の変数(=クラスのインスタンス=cMeオブジェクトを1個宣言)
  //メモリ上に1個のcMe型の変数が用意される。名前はwatashi
  cMe arr_me[5]; 
 
  //メモリ上に5個のcMe型の変数が用意される。名前はarr_me
  arr_me[0].m_age = 15;
  arr_me[1].m_age = 60;
  arr_me[2].m_age = 50;
  arr_me[3].m_age = 25;
  arr_me[4].m_age = 88;
  //普通の配列みたいにアクセスできて、普通のクラスのインスタンスみたいにアクセスできるよ
  return 0;
}
 
ここまできっと、理解しやすいと思います。\\
次、これを、動的に確保します。\\
動的確保=プログラムが動き始めてから、必要な量の変数を必要な分だけメモリ上に用意すること。\\
静的確保=通常の配列は、数があらかじめ宣言されていて、コンパイルの時には必要なメモリ量が確定している。\\
   
**配列の静的確保**\\
初めのほうに習ったオーソドックスな配列の宣言方法。\\
数をはじめに書いておいて、その数だけの変数を使ってたよね\\
<code cpp>
int i_arr[10];
float f_arr[20];
cMe me_arr[5];

ここで、配列の名前は、配列の先頭アドレスへのポインタになってるんだったね。

配列の動的確保
そんで、C++で変数を動的に確保するには以下のようにするんでしたね?
覚えてる?
  new 型名[要素数];   で、指定した型の配列要素数分だけメモリ上に確保して、その先頭のアドレスが返ってきます。
帰ってきた値は、変数に入れとかないと使えないので、アドレスを入れておく入れ物=ポインタ変数を用意します。
これで、先頭アドレスをポインタに保存してしまえば、静的配列と全く同じように使えます。

#include <iostream>
 
int main() {
  int num;
  int *arr = nullptr;
  //配列にアクセスするためのポインタを用意
  std::cin >> num;
  //num個の配列が欲しい
 
  arr = new int[num];
  //配列を確保して、先頭アドレスをarrに代入
 
  for (int i = 0; i < num; i++) {
    arr[i] = i + 1; 
    //先頭アドレスをポインタに入れてさえしまえば通常の配列と同じようにアクセスできる
  }
 
  return 0;
}

んで、やっとオブジェクト配列

オブジェクト配列とか言ってますが、ただの配列です。
通常の組み込み型(int, char, floatなどのもとからある型)の配列と違うのは、クラスのインスタンスが配列としてメモリ上に並んでいることです。
( JavaとかC#はintの変数もオブジェクトっていうので、配列はすべてオブジェクト配列なんだよねぇ。C++うぇ。。。)
要は、インスタンス配列って事です。さらにそれを動的に確保します。
やり方は、以下の通りです。

new クラス名[要素数];   で、指定したクラスのインスタンス配列要素数分だけメモリ上に確保して、その先頭のアドレスが返ってきます。
帰ってきた値は、変数に入れとかないと使えないので、アドレスを入れておく入れ物=ポインタ変数を用意します。
これで、先頭アドレスをポインタに保存してしまえば、静的配列と全く同じように使えます。

#include <iostream>
 
class cMe {
public:
  int m_age;
};
 
int main() {
  cMe watashi;
  cMe *p = nullptr;
 
  int num;
 
  std::cin >> num;
 
  p = new cMe[num];
  for (int i = 0; i < num; i++) {
    p[i].m_age =  i + 20;
  }
 
  return 0;
}