2018年04月16日
《その362》「関数へのポインタ」「データメンバへのポインタ」 の受渡し
「関数へのポインタ」「データメンバへのポインタ」 の受渡し
ブログの記事が多くなってきたので、「C++ 全記事目次」を右側に設置しました。
これで調べてみると、今回の記事は、《164》〜《166》辺りの復習ということになります。
下記のプログラムは複雑に見えますが、やっていることは非常に単純です。
Aaa型オブジェクト obj_a のデータメンバ num の値である 1326 と、str の値である "Yamada" を表示するだけなので、
内容的には、
cout << obj_a.num << '\n';
cout << obj_a.get_str() << '\n';
の2行で済む話です。
以下は、プログラムの説明です。
◆main関数は、データ出力用の関数 f を、2回呼び出します。
1回目と2回目の違いは、引数として渡す関数へのポインタが func1 であるか func2 であるか、だけです。
※関数名 func1, func2 は、その関数へのポインタとみなされます。
◆クラスのメンバへのポインタでは、ポインタ型、すなわち
・データメンバへのポインタ型
・メンバ関数へのポインタ型
が、少し複雑な形式なので注意が必要です。プログラムのコメントとコードをご覧ください。
◆main関数は、
クラスオブジェクト
クラスオブジェクトのデータメンバへのポインタ
クラスオブジェクトのメンバ関数へのポインタ
関数名
の4つを引数として、関数 f を呼び出します。
◆関数 f は、main関数から4つの引数を受け取ります。
それらを受け取る仮引数の書き方も少し複雑です。プログラムのコメントとコードをご覧ください。
◆関数 f は、main関数からの指示に従って、func1 あるいは func2 を呼び出します。
f_pointer(x, p, fp);
受け取った引数を、そのまま渡すだけなので簡単です。
◆関数 func1, func2 の3つの仮引数は、関数 f の引数と同じものです。
2つの関数 func1, func2 は、出力表示の形が少し違うだけです。
プログラムとしては、全く意味のないものですが、
・関数への ポインタ定義とその受渡し
・クラスのデータメンバへの ポインタ定義とその受渡し
・クラスのメンバ関数への ポインタ定義とその受渡し
を確認することができます。
以下は、プログラムです。
#include <string>
#include <iostream>
using namespace std;
class Aaa
{
string str;
public:
int num;
Aaa(string s, int n = 10)
: str(s), num(n) { }
string get_str() const{ return str; }
};
// 仮引数がわかりにくい形をしていますが、この説明は、
// 関数 f の仮引数のところでしています。
void func1(Aaa& x, int Aaa::* p, string (Aaa::* fp)() const)
{
// 間接ドット演算子を利用して、
// Aaa::num にアクセスしています。
cout << x.*p << '\n';
// メンバ関数へのポインタを使って、
// Aaa::get_str関数を呼び出します。
cout << (x.*fp)() << '\n';
}
void func2(Aaa& x, int Aaa::* p, string (Aaa::* fp)() const)
{
cout << "氏名 : " << x.*p << '\n';
cout << "番号 : " << (x.*fp)() << '\n';
}
void f(
// f_pointer は、
// 関数 func1 あるいは func2 を指すポインタ
// を受け取るための仮引数です。
// 関数の型を明記する必要があります。
void (*f_pointer)(Aaa&, int Aaa::*, string(Aaa::*)() const),
// x は、Aaa型オブジェクトへの参照を受け取るため
// の仮引数です。
Aaa& x,
// p は、Aaa型オブジェクトの int型データメンバ
// へのポインタを受け取るための仮引数です。
int Aaa::* p,
// fp は、Aaa型オブジェクトのメンバ関数 get_str
// を指すポインタを受け取るための仮引数です。
string (Aaa::* fp)() const
) {
cout << "------\n";
// 引数に受け取った関数 f_pointer、すなわち
// func1 または func2 を呼び出します。
// 引数 x, p, fp は受け取ったものをそのまま
// 使っています。
f_pointer(x, p, fp);
}
int main() {
// Aaa型オブジェクト obj_a を生成します。
Aaa obj_a("Yamada", 1326);
// ptr はデータメンバ Aaa::num を指すポインタです。
int Aaa::* ptr = &Aaa::num;
// fptr はメンバ関数 Aaa::get_str を指すポインタです。
string (Aaa::* fptr)() const = &Aaa::get_str;
// func1 は関数 func1 を指すポインタです。
f(func1, obj_a, ptr, fptr);
// func2 は関数 func2 を指すポインタです。
f(func2, obj_a, ptr, fptr);
}
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/7556064
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック