Help us understand the problem. What is going on with this article?

メンバー関数ポインタと配列を使って、メンバー関数を番号で指定して呼び出す方法

More than 5 years have passed since last update.

備忘録ですが、せっかく記事にするので体裁を整えて記述したいと思います。

はじめに(事例)

公開クラスの関数に、番号を指定することで挙動を変えたいのですが、どのように書けばよいのでしょうか?

コード

#include <iostream>
#include <memory>

// 実務クラスのプライベートメンバー関数を番号で指定して呼び出したい。
// 参考書の通りに書くと、プライベート非staticメンバー関数・・・

using ub4 = unsigned int;

// 外部に公開して利用するクラス
class A {
public: // クラスの外で using を使いたいので public にしている。
    class impl; // 実務クラスの宣言
private:
    std::unique_ptr<impl> pim;
public:
    A();
    ~A();
public:
    void func_call( ub4 fn_num );
};

// メンバー関数ポインタへの型を宣言
using a_fn_ptr_t = void ( A::impl:: * )();

// 実務クラス
class A::impl {
    static constexpr ub4 pf_num = 4; // 定数で配列の要素数を指定
    static a_fn_ptr_t func_ar[ pf_num ];
public:
    impl();
    ~impl();
public:
    void func_call( ub4 fn_num );
private:
    void func_00();
    void func_01();
    void func_02();
    void func_03();
};

// 配列にメンバー関数ポインタを入れる
a_fn_ptr_t A::impl::func_ar[] = {
    &A::impl::func_00,
    &A::impl::func_01,
    &A::impl::func_02,
    &A::impl::func_03
};

A::A() :
    pim ( new impl() )
{}

A::~A()
{}

void A::func_call( ub4 fn_num )
{
    pim->func_call( fn_num );
}

A::impl::impl()  { printf("A::impl::impl() \n");}
A::impl::~impl() { printf("A::impl::~impl()\n");}


void A::impl::func_call( ub4 fn_num )
{
    if( fn_num >= pf_num ) return; // 申し訳程度のチェック
    ( this->*( func_ar[ fn_num ] ) )(); // 配列に入っているメンバー関数を呼び出し。
}

// 何らかの実務関数
void A::impl::func_00() { printf("A::impl::func_00()\n"); }
void A::impl::func_01() { printf("A::impl::func_01()\n"); }
void A::impl::func_02() { printf("A::impl::func_02()\n"); }
void A::impl::func_03() { printf("A::impl::func_03()\n"); }


// 実際に使えるかテストしてみる。
int main()
{
    A a;
    a.func_call( 0 );
    a.func_call( 1 );
    a.func_call( 2 );
    a.func_call( 3 );
    a.func_call( 4 );
    a.func_call( 5 );
    a.func_call( 6 );

    return 0;
}

結果


Start

A::impl::impl() 
A::impl::func_00()
A::impl::func_01()
A::impl::func_02()
A::impl::func_03()
A::impl::~impl()

0

Finish

参照

Wandboxにて確認させて頂きました。
http://melpon.org/wandbox/permlink/bqi7Pu16WuetcmJ9

C++11参考書:関数呼び出し(Function call)
http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml#expr.call

C++11参考書:メンバーへのポインター演算子(Pointer-to-member operators)
http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml#expr.mptr.oper

C++11参考書:非staticメンバー関数(Nonstatic member functions)
http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml#class.mfct.non-static

その他

コードの色付けが無いとさっぱり分からないです。
ちなみに私の環境
windows7 64bit
Microsoft Visual Studio Express 2013 for Windows Desktop
では、以下のように表示させています。

sample_code.jpg.jpg

色が赤くなるほどなんかヤバイ感じ、気を付けなきゃいけない感じが出るようにしているのですが、これはそのうち別記事に書こうかなと思います。

あと
非staticメンバー関数  という記述の仕方は最初とまどいますね。
一般人の私にとっては  普通のメンバー関数 と記述したいところです。

以上です。

何か指摘事項がございましたら、お気軽にコメントお願いしまーす。

shiro_naga
超局所的な実務事例に基づいた記事を書きたいです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした