第十四回-02 Studentクラスの様々な呼び出し方

Student クラスの呼び出し方として以下の二つを学ぶ

引数つきのコンストラクタでの呼び出し

第十四回-01では、Student クラスを以下のように利用していた。

(main 関数内)

	Student s1;      // 引数なしコンストラクタが呼ばれる

	s1.setStudent(100,"織田信長");

	s1.printInfo();

このとき、「Student s1;」と書いた時点で「引数なしのコンストラクタが呼ばれる」とのコメントがあるが、
引数なしのコンストラクタとはなんだったかというと、Student.cpp 内で記述された以下のもののことである。

(Student.cpp 内)

// 引数なしのコンストラクタ
Student::Student()
{
	ID = 0;
	name = "";
}

つまり、「Student s1;」 と書いた時点では、ID=0 で名前は空となった状態である。
そこで「s1.setStudent(100, "織田信長");」を呼んだ時点で ID と name がセットされる。

一方、変数 (インスタンス) の宣言と同時に ID と name をセットする方法もある。 それが以下に示す方法である。

見慣れない表現かもしれないが、変数の宣言と同時に引数として 100, "織田信長" が渡されている。

(main 関数内)

	Student s2(101, "明智光秀");      // 引数ありのコンストラクタが呼ばれる

	s2.printInfo();

これにより、以下の引数ありのコンストラクタが呼ばれ ID と name が即セットされる。

// 引数ありのコンストラクタ
Student::Student(int i, string n)
{
	ID = i;
	name = n;
}

引数なしの場合と比べると、「s2.setStudent(101, "明智光秀");」の命令が不要になっていることがわかる。
つまり、引数ありのコンストラクタの方が、データメンバ (ID と name) が確実に初期化される、というメリットがある。


Studentクラスのポインタでの使い方

次に、Student クラスをポインタで利用する例を見てみよう。

例えば int 型に通常の変数とポインタ変数があったように、クラスにも通常の変数とポインタ変数とが存在する。
クラスにおいてポインタの利用は避けられない事が多い。本ページではそのために必要な知識を学ぶ。
なお、本項目は第十三回-03とほぼ同内容である。

main 関数における実際の使用例がこちら。ポインタでも引数なしとありとのコンストラクタ呼び出しがあるので、両方記す。

	Student *sp1;
	sp1 = new Student();  // 引数なしコンストラクタでの呼び出し
	sp1->setStudent(102, "豊臣秀吉");
	sp1->printInfo();

	Student *sp2;
	sp2 = new Student(103, "徳川家康");  // 引数ありコンストラクタでの呼び出し
	sp2->printInfo();

	delete sp1;  // new でメモリ確保したものは自分で delete する
	delete sp2;  // new でメモリ確保したものは自分で delete する

さて、やっていることはこれまでとほとんど変わらないのだが、
よくよく見ると記述が微妙に異なる。順に見て行こう。

まず、ポインタ変数の宣言が以下である。これは int 型など通常の型に対するポインタ変数と同様で、アスタリスク ( * ) をつければよい。 次に、ポインタに対して新たなメモリ領域を確保してオブジェクトを生成している行 がある。これは第十一回「new 演算子によるメモリの動的確保」 に類似しているので復習しておいて欲しい。
これにより、下図のようにヒープ領域にオブジェクトが確保され、ポインタ sp1、sp2 はそちらを指すようになる。
通常の変数 s1、s2 の場合との違いに注意しよう。



そして、メンバ関数の呼び出し。ここが一番目立つ違いであろう。 ポインタ変数からのメンバ関数の呼び出しは、このようにドット演算子 ( . ) ではなく
アロー演算子 ( -> ) を用いる。これは、上のメモリの模式図を想像するとイメージしやすいかも知れない。

そして最後に、new で確保したメモリは delete で解放する。これは第十一回「new 演算子によるメモリの動的確保」 に類似しているので復習しておこう。 このように、C++ では変数からのメンバ関数呼び出しはドット演算子、 ポインタからのメンバ関数呼び出しはアロー演算子、と使い分ける
のが特徴であり、後に登場した Java や C# に比べると繁雑なところである。

Java や C# ではメンバ関数の呼び出しは全てドット演算子で統一されている。
なお、Java や C# でのクラス変数は全て内部的にはポインタのような振舞いをするので、
new でメモリ確保する点など、利用法はむしろ C++ でのポインタに似ている。

最後に int などの型とクラスとで、通常の変数とポインタ変数の利用法の違いを整理しておこう。

宣言 アドレス
通常の変数 int x x &x
ポインタ変数 int *x *x x


宣言 実体 アドレス メンバ関数呼び出し
通常の変数 Student s s &s s.func()
ポインタ変数 Student *s *s s s->func()




←第十四回-01 Student クラスを作ってみよう第十四回-03 Studentクラスの配列と>コレクション→

非情報系学生のための C/C++ 入門に戻る