2017年12月06日
《その164》 メンバ関数へのポインタ
クラスのメンバ関数へのポインタ
クラスのメンバ関数を、直接呼び出すのではなく、目的の関数へのポインタを通じて動的に呼び出すことを考えます。
次のプログラムは、記念日が何年年月何日であるかを当てさせる単純なものですが、コード中にコメントとして、メンバ関数へのポインタの記述方法やそれに関連したことを書き込みました。
// ------------------------------------
#include <ctime>
#include <cstdlib>
#include <iostream>
using namespace std;
class Anniversary {
// 記念日クラス Anniversary は
// 日付( 1980/01/01 〜 2017/12/31 )を1つだけ保持します。
int y, m, d;
public:
Anniversary() {
srand((unsigned)time(NULL));
y = rand() % 38 + 1980; // 1980 〜 2017
m = rand() % 12 + 1; // 1 〜 12
switch (m) {
case 2: d = rand() % 28 + 1 + (
y % 4 == 0 && y % 100 != 0 ||
y % 400 == 0); // うるう年を考慮
break;
case 4:
case 6:
case 9:
case 11: d = rand() % 30 + 1; break;
default: d = rand() % 31 + 1; break;
}
}
int yy() const { return y; }
int mm() const { return m; }
int dd() const { return d; }
};
int main() {
Anniversary date;
// Anniversaryクラスの dateオブジェクトを作成。
// 日付を1つ保持しています。
cout << "記念日( 1980/01/01 〜 2017/12/31 )を当ててください。\n";
typedef int (Anniversary::*Anniv)() const;
// Anniversaryクラスのメンバ関数 yy, mm, dd は、仮引数無し、
// 返却値 int ですから、これらのメンバ関数
// へのポインタ型は、次のようになります。
// int (Anniversary::*pointer)()
// このメンバ関数へのポインタ型に typedef名 Anniv を与える
// には、const関数でもあることを考慮して、
// typedef int (Anniversary::*Anniv)() const; と記述します。
Anniv ymd[] = {
&Anniversary::yy,
&Anniversary::mm,
&Anniversary::dd
};
// 配列 ymd は、Anniv型を要素型とする配列で、その要素数は
// 3 です。
// ymd[0] は Anniversary::yy を指し、
// ymd[1] は Anniversary::mm を指し、
// ymd[2] は Anniversary::dd を指すことになります。
int menu; // 配列 ymd の添字(要素番号 0 〜 2)です。
// 配列 answer の添字でもあります。
int val; // 入力された値を受け取るための変数です。
int answer[3] = { 0 }; // 年が正解したら answer[0] = 1
// 月が正解したら answer[1] = 1
// 日が正解したら answer[2] = 1
do {
do {
cout << "年(0) 月(1) 日(2) のどれを入力しますか : "; cin >> menu;
} while (menu < 0 || menu > 2);
cout << "値を入力 : "; cin >> val;
if (val == (date.*ymd[menu])()) {
// date.*ymd[menu] は、
// (date.*ymd[0])() のときは、date.yy() のこと、
// (date.*ymd[1])() のときは、date.mm() のこと、
// (date.*ymd[2])() のときは、date.dd() のことになります。
cout << "正解です。\n";
answer[menu] = 1;
}
else {
cout << (date.*ymd[menu])() - val << " を加えてください。\n";
answer[menu] = 0;
}
} while (answer[0] == 0 || answer[1] == 0 || answer[2] == 0);
cout << date.yy() << "年" << date.mm() << "月" << date.dd() << "日\n";
}
// ------------------------------------
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/7059808
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック