昔、「2次方程式の解の公式」なんてありましたね。数学の先生があれを黒板で導いたのを見て、すぐ「なるほど、わかった」と、思った人もいるでしょうが、普通の人(私なんかです)は、それより、例題を解いていてなんとなくわかったような気がしたのではないでしょうか?えーと、数学の話なんかしてすみません。
つまり、わかろうと考え込むより、やってみる方がわかるのでは、という話です。プログラムの場合、「コンパイル・実行」->「改造」->「コンパイル・実行」->「改造」->・・・を繰り返すのがよいと思うのです。はじめは単純なタイプミスでコンパイルエラーがでますが、そのうち、タイプミスはすぐに探せるようになります。そうこうしているうちに、おっかなびっくりでなく(簡単な)プログラムが作れるようになってきます。そしてわかったような気がしてくるから、不思議です。
クラスの書き方はわかりましたか?まだ、しっくりこないかもしれませんね。今回は、復習しながら単純なクラスを作ってみます。その過程で、少し新しいことも説明しましょう。
もう一度前回の分を読み直して...なんていいですから、今回の分を最後のプログラムのところまでさっと読んでみてください。それから、前回の分を読み直すのもよし、今回の分を精読するのもよしです。お勧めは、やっぱり、「プログラムをコンパイル・実行してみる」です。^^)
さて、どんなクラスを作ってみましょうか?と、考えるのもたのしいですね。今日は「ロケット」をつくってみます。ロケットの持つべき「データ」(つまり、メンバ変数・データメンバ)と「動作・機能」(つまりメンバ関数)は何でしょうか?私なら、次のように考えます。
クラス ロケット
データメンバ:燃料
現在の速度
メンバ関数 :コンストラクタ
加速
まあ、はじめはこんなもんでしょう。ロケットに名前をつけたい、発射の仕掛けもつくりたい、など、要望は多々あるでしょうが、はじめは簡単にします。
前回書いたように、基本的に、メンバ変数はprivate、メンバ関数はpublicとします。そして、燃料と速度は、簡単に整数としましょう。するとintを使えばいいですね。それぞれnenryo、sokudoとします。
それから、コンストラクタを考えましょう。どんなクラスでもコンストラクタを書かなければいけないということではありません。しかし、たいていの場合は必要になります。ということで、ここでもコンストラクタを書きます。(コンストラクタを書かない場合については、次回に説明します。)
コンストラクタで書くことは、基本的に、「生成されるオブジェクトにどのようなデータを与えるか」が中心です。「猫」のときは名前を与えました。このようにメンバ変数の値を決めてやるのがコンストラクタの主な仕事なのです。これをオブジェクトの(データの)初期化なんて言います。「オブジェクト」はメモリ上の「もの」(名前のついた具体的な「猫」や「ロケット」)という意味でした。「初期化」とは一般に「データなどをはじめに決めてやる」という意味なのです。さあ、どう初期化しましょうか。たとえば、燃料を引数で決めてやって、速度を0にすればいいでしょう。
(「コンストラクタ」も「引数」も初心者にはわかりにくいですね。上に書いたように「コンストラクタ」はオブジェクトを生成するときに使うものです。「引数」はコンストラクタなど関数のカッコの中にいれるデータのことでした。ここで考え込まずに下の使用例を見てください。)
加速のメンバ関数はどうしましょうか。加速は物理学の法則によると、、、なんてやめましょう。加速一回で速度が適当に(私は2とします。もちろん深い理由はないので別の数でもかまいません)上がるようにしましょう。そのとき、当然燃料が減るはずですね。同じ数字(つまり2)だけ燃料が減るようにしましょう。以上をまとめると、ロケットのクラスRocketは次のようになります。
class Rocket //スペルをまちがえるとかなり恥ずかしいので辞書を見ましょう
{
int nenryo; //燃料
int sokudo; //現在の速度
public:
Rocket(int); //コンストラクタの宣言
void kasoku(); //加速を表す関数の宣言
};
//コンストラクタの定義
//nenryoに引数として与えられる値(xで表す)を入れ、sokudoに0を入れているだけです
Rocket::Rocket(int x) : nenryo(x), sokudo(0){}
//加速を表す関数の定義ですが、なんだこりゃ。これも下の説明参照。
void Rocket::kasoku(){
sokudo += 2;
nenryo -= 2;
}
です。これは、変な式ですが、それぞれ「sokudoに2を足せ」「nenryoから2を引け」という意味になるのです。「+=」「-=」は、それぞれ「右辺のものを左辺に足せ」「右辺のものを左辺から引け」という意味になると、そう決めてあるからです。(つまり、そういうものだと、ここでおぼえてください。)
実はこれらは
sokudo = sokudo + 2;
nenryo = nenryo - 2;
kasoku()の中身は2つのブロックにわかれています。と、言っても最初はわからないでしょう。ifのブロック(ifの横の{から3行下の}まで)とelseのブロック(elseの横の{から2行下の}まで)です。ifのすぐあとの丸カッコ内の式「nenryo >=
2」は条件を表しています。ここは
もし、nenryoが2以上ならば、
などと読みます。この「>=」はイコールが下についた不等号のかわりです。(高校生が「大きいかまたは等しい」とかなんとかと読むやつです。)nenryoは一回の加速に2使うので、それが2以上なければ、もう燃料切れで、加速できないと考え、そのチェックをしているのです。
そして、もしnenryoが2以上なら、はじめに考えたようにsokudoに2を足し、nenryoから2を引きます。また、ついでにその時の燃料と速度を表示するようにしました。それがifのブロックに書いてあることです。
elseは
そうでなければ、
などと読みます。つまり、ここでは「nenryoが2以上でなければ」という意味ですね。その場合は、燃料切れという意味ですから、ロケットは加速せず漂流としました。それがelseのブロックに書いてあることです。 それでは、このRocketクラスを使った、またまた簡単なプログラムを書いてみます。
//RocketSample.cpp
#include <iostream>
using namespace std;
class Rocket //改良版ロケット
{
int nenryo; //燃料
int sokudo; //現在の速度
public:
Rocket(int x); //コンストラクタ
void kasoku(); //加速を表す関数
};
//コンストラクタの定義
Rocket::Rocket(int x) : nenryo(x), sokudo(0){}
//加速を表す関数の定義
void Rocket::kasoku()
{
if(nenryo >= 2){
sokudo += 2;
nenryo -= 2;
cout<< "現在の燃料は" << nenryo << "です。" <<
endl;
cout<< "現在の速度は" << sokudo << "です。" <<
endl;
}
else{
cout << "燃料切れです。加速できません。漂流です。"
<<endl;
}
}
int main()
{
cout << "ロケットをメモリ上につくります。燃料(整数)を入力してください。"<<endl;
int n; //ユーザの入力した値を格納する変数をひとつ用意しました。その名はnです。
cin >> n; //ユーザの入力した数字をnに代入しました。
//nをコンストラクタに渡してロケットをつくります。
Rocket ohtori(n); //これでnの値がコンストラクタの定義のxにコピーされ、
//コンストラクタの中身が実行され、nenryoの値がnの値に
//なったロケットohtori(鳳号)が生成されるわけです。
//このohtoriをオブジェクトなどとよぶのでした。
cout<< "加速します。" <<endl;
ohtori.kasoku();
//ohtoriに対してkasokuを使っています
cout<< "また、加速します。" <<endl;
ohtori.kasoku();
//ohtoriに対してkasokuを使っています
cout<< "またまた、加速してみます。" <<endl;
ohtori.kasoku();
//ohtoriに対してkasokuを使っています
cout<< "鳳号の冒険は終わりました。" <<endl;
}
Fig.1 RocketSample.exeの実行画面1(燃料をはじめに30にした)
Fig.2 RocketSamle.exeの実行画面2(燃料をはじめに4にした)
解説はあまりいらないと思うのですがどうでしょうか。mainの中では、Rocketクラスのオブジェクトohtoriを作り、それを3回加速させているだけです。Rocketクラスの使い方、つまり「オブジェクトの生成とメンバ関数の使い方」を見ておいてください。
一言コメントをしておきます。ohtoriは、「Rocketの変数」ということができますが、C++では、「クラス型の変数」は「オブジェクトそのもの」を意味すると考えることができるのです。(関係ありませんが、Javaなどでは、変数とオブジェクトを区別する必要があるのでした。Javaプログラマの人は注意してください。)
鳳号(ohtori)は3回加速していますね。もし、燃料切れにならなければ、速度が増えて、、、それだけです。もし、はじめの燃料がたりなければ、つまり、5以下なら、途中で漂流するでしょう。う〜ん。プログラムとしてはあんまりおもしろくないですね。(それでも、コンピュータが思いどうり動いてくれて、楽しいとは思うのですが、、、。)でも、まあ基礎ですから。基礎は飽きてきたという人、もう少し待ってください。(注:子供の頃に見た「妖星ゴラス」という映画はとても印象的でした。その映画に出てきたかっこいいロケットが鳳号という名前でした。深い意味はないのですが。)
最後に、if文のまとめを書いておきます。ざっとながめておいて、必要になったときに、見るようにしてもよいでしょう。
if文とは、一般に、
if(条件a){ のような形をしていて、、条件aが正しいとき処理Aが実行され、そうではなくて条件bが正しいときは処理Bが実行され、...となり、どの条件も正しくないときは、処理Zが実行される、というものです。ただし、ここで、「else if(...){...}」はいくつあっても(なくても)かまわないし、また、「else{...}」の部分は、なくてもかまいません。 |
また、条件は次のように書きます。
aとbに対して、条件の書き方
a == b aとbが等しい(とき) |