クラス 資産家猫
データメンバ:資産
メンバ関数 :コンストラクタ(名前と資産を初期化)
年収を表示する関数
//sisanneko.cpp
#include <iostream>
#include <string>
using namespace std;
class Neko
{
string name; //名前
public:
Neko(string); //コンストラクタ
void naku() const;
};
Neko::Neko(string s) : name(s){}
void Neko::naku() const{
cout << "にゃあ。俺様は" << name << "だ。"
<< endl;
}
class SisankaNeko : public Neko
{
int sisan; //資産、万円単位
public:
SisankaNeko(string, int); //コンストラクタ
//年収を戻す関数。年収は資産の利子のみで、利率は2%とする。
int get_nensyu() const{ return sisan * 2 / 100;}
};
SisankaNeko::SisankaNeko(string n, int s) : Neko(n), sisan(s){}
int main()
{
string n;
int s;
cout << "資産家猫をメモリ上に生成します。名前を決めて入力してください。"
<< endl;
cin >> n;
cout << "資産を決めて入力してください。(単位:万円)"
<< endl;
cout << "(数字は半角で入力してください。)"
<< endl;
cin >> s;
SisankaNeko dora(n, s); //資産家猫の生成
//無限ループ。抜けるにはユーザが1、2以外の数字を入力すればよい。
while(1){
cout << "どうしますか?"
<< endl;
cout << "1 鳴かす 2
年収を表示 3 やめる" << endl;
int ans;
cin >> ans;
if(ans == 1){
//Nekoの関数nakuをSisankaNekoが使う。
dora.naku();
//Nekoのnaku()はSisankaNekoでも使えるのです。
}
else if(ans == 2){
cout <<
"年収は現在" << dora.get_nensyu()<< "万円です。"
<< endl;
}
//上のどれも成り立たない場合。ユーザには「3
やめる」と表示したが、
//1、2以外ならループを抜けるようにした。
else{
break;
}
//見やすさのための改行
cout << endl;
}
cout << "おしまい" << endl;
}
どうでしょうか?それにしても、銀行にお金を預けておいて利子が2%なんて2004年12月現在、「ぶっちゃけありえねー」ですね。
//jimbutu_game.cpp
#include <iostream>
#include <cstdlib> //乱数に必要、入門10を参照
#include <ctime> //乱数に必要
using namespace std;
//人物、剣士や占い師などの基底クラス
class Jimbutu
{
int power;
public:
//コンストラクタ、powerを初期化
Jimbutu() : power(5){}
int get_power() const { return power; }
//仕事をした後にパワーを減らす関数
void decr_power(){
power--;
cout << "現在のパワー:"
<< power << endl;
}
};
//剣士
class Kensi : public Jimbutu
{
public:
void sigoto(); //剣士の仕事、定義はクラス宣言の外で、、、
};
void Kensi::sigoto()
{
//get_power()でパワーを調べ、0以下なら何もしない。
if(get_power() <= 0){
cout << "すまん。疲れているんだ。"
<< endl;
return; //この関数「sigoto」から抜ける。
}
cout << "俺は剣士だ。俺の剣技を見せてやる。"
<< endl;
cout << "どりゃ〜。おりゃ〜。そりゃ〜。、、、以上。"
<< endl;
decr_power(); //Jimbutuの関数
}
//占い師
class Uranaisi : public Jimbutu
{
public:
void sigoto(); //占い師の仕事、定義はクラス宣言の外で、、、
};
void Uranaisi::sigoto()
{
//get_power()でパワーを調べ、0以下なら何もしない。
if(get_power() <= 0){
cout << "わしゃ〜占い師じゃが、腹減って動けんよ。"
<< endl;
return; //この関数「sigoto」から抜ける
}
cout << "私は占い師じゃ。今日のおまえの運勢を占ってやろうかの。"
<< endl;
int x = rand() % 3;
//上の1行は「int x;
// x=rand()%3; 」 と同じ意味です
if(x == 0){
cout << "おまえの今日の運勢は最高じゃ。"
<< endl;
}
else if(x == 1){
cout << "今日のおまえは、まあ、普通じゃな。"
<< endl;
}
else if(x == 2){
cout << "今日はおまえの厄日じゃ。何もせん方がよい。"
<< endl;
}
decr_power(); //Jimbutuの関数
}
int main()
{
srand( (unsigned)time( NULL ) );
Kensi hero; //剣士ヘロの誕生
Uranaisi pero; //占い師ペロの誕生
while(1){
int x;
cout << "どうします?"
<< endl;
cout << "1
剣士に仕事をしてもらう。 2 占い師に仕事をしてもらう。 3
やめる" << endl;
cin >> x;
if(x == 1){
hero.sigoto();
}
else if(x == 2){
pero.sigoto();
}
else{
break;
}
}
cout<<"おしまい。"<<endl;
}
どの登場人物(Jimbutu)もパワーを持ち、この値は引数を取らないコンストラクタで5に設定するようにしました。現在のパワーを報告させる関数get_power()は派生クラスで使われます。関数decr_power()は、派生クラスのオブジェクトが仕事をしたときに呼び出され、その人物のパワーを減らすのです。ついでに、そのときのパワーを表示するようにしておきました。あと、日本語と英語が混じっていてすみません。これは反省してるのですが、、、こうなちゃったので、このままいきます。
いくつかの注意があります。
まずは些細なことです。main()のはじめに乱数の初期化をしていますが、ここに置くのは私の趣味ではありません。(趣味は人それぞれですが。)本来なら、入門9のTaiketu_basyoのように登場人物たち全員を「入れる」あるいは「制御する」クラスをつくり、そのクラスで初期化をしたいところです。しかし、プログラムが長くなるので、やめました。
派生クラス「剣士(Kensi)」「占い師(Uranaisi)」にはコンストラクタを定義しませんでした。これでもよいのです。mainの中では、KensiやUranaisiのオブジェクト(heroとpero)を生成していいますが、ここでは、基底クラスであるJimbutuの引数を取らないコンストラクタが使われます。
それと、ずっと気になっていたことがあります。それは、変数を定義する場所です。変数を定義する場所は、使われる前ならどこでもよいのです。しかし、どこでもよいというのは便利ですが、はっきり決められないので、一歩間違えれば不便にもなります。今までの例ではわかりやすくするのに、変数は使う直前で定義してきました。つまり、
int x;
cin >> x;
などと書いてきたわけです。これに間違いはありません。しかし、もし、この変数をもっと後の場所でも使いたいなら、その場所まで含めた範囲の中で、一番最初にするべきです。つまり、上のように書いておいてずっと後でまたxを使うと、半年後の自分や別の人が後の方のxを見て「あれ、このxどこで定義したものかな」と考え込んでしまうからです。そう考えてwhile(1)中のxの位置を決めました。簡単に言うと(いつもというわけではないですが)変数が使われる{ }内の一番最初が普通は妥当だと思います。要は見やすさの問題なのですが。(これでいくと、main()中のKensi
hero;とUranaisi pero;の位置が少し変ですね。これは上に書いたように、本当は別のクラスをつくりたいところを省略したからです。)
それから、if(やelse)文なんですが、内容が1行のときは、{ }はいりません。つまり、例えば、
if(x == 1){
cout << "hello!"
<< endl;
}
と
if(x == 1)
cout << "hello!"
<< endl;
if(x == 0){
cout << "おまえの今日の運勢は最高じゃ。"
<< endl;
}
else if(x == 1){
cout << "今日のおまえは、まあ、普通じゃな。"
<< endl;
}
else if(x == 2){
cout << "今日はおまえの厄日じゃ。何もせん方がよい。"
<< endl;
}
//サンプルにはなかったがelseを付け足す
else{
cout << "エラーじゃあ"
<< endl;
}
switch(x){
case 0:
cout <<
"おまえの今日の運勢は最高じゃ。" << endl;
break;
case 1:
cout <<
"今日のおまえは、まあ、普通じゃな。" << endl;
break;
case 2:
cout <<
"今日はおまえの厄日じゃ。何もせん方がよい。"
<< endl;
break;
default:
cout <<
"エラーじゃあ" << endl;
}