C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++のメンバー関数ポインタの基本と使い方をわかりやすく解説

C++では、クラスや構造体のメンバー関数を指す関数ポインタは、通常の関数ポインタとは少し扱い方が異なります。メンバー関数はオブジェクトに紐づいて動作するため、呼び出し時にはオブジェクトへのポインタ(または this 呼び出し)を介して実行する必要があります。

また、メンバー関数ポインタは型安全であるという特徴があります。つまり、特定のクラス型に対して定義されたポインタは、そのクラス自身(またはその派生クラス)のメンバーしか呼び出すことができません。これにより、誤ったクラスのメンバー関数を呼び出してしまうミスをコンパイル時に防ぐことができます。

メンバー関数ポインタの宣言方法

メンバー関数ポインタは、次のような構文で宣言します。

戻り値の型 (クラス名::*ポインタ名)(引数の型リスト);

例えば、int(AB::*fp)(int,int) は「クラス AB の、int を2つ受け取り int を返すメンバー関数」を指すポインタです。呼び出し側では &AB::sub のようにクラススコープとアドレス演算子を使って取得し、(obj->*fp)(m,n) のように ->* 演算子で実行します。

サンプルコード

以下は、メンバー関数ポインタを使って減算と除算を行う例です。同じ仕組みを持つ2つの関数 res1res2 が、それぞれ別のメンバー関数ポインタを受け取って処理を実行しています。

#include <iostream>
using namespace std;

class AB {
public:
    int sub(int a, int b) {
        return a - b;
    }
    int div(int a, int b) {
        return a / b;
    }
};

// 関数ポインタを使用する関数
int res1(int m, int n, AB* obj, int(AB::*fp)(int, int)) {
    return (obj->*fp)(m, n);
}

// 関数ポインタを使用する関数
int res2(int m, int n, AB* obj, int(AB::*fp2)(int, int)) {
    return (obj->*fp2)(m, n);
}

int main() {
    AB ob;
    cout << "Subtraction is = " << res1(8, 5, &ob, &AB::sub) << endl;
    cout << "Division is = " << res2(4, 2, &ob, &AB::div) << endl;
    return 0;
}

実行結果

Subtraction is = 3
Division is = 2

コードのポイント

  • &AB::sub:クラス AB のメンバー関数 sub のアドレスを取得します。通常の関数と違い、クラス名で修飾する必要があります。
  • (obj->*fp)(m, n):オブジェクトポインタ経由でメンバー関数ポインタを呼び出します。オブジェクトそのものを使う場合は (obj.*fp)(m, n) となります。
  • 型安全性res1res2 に渡せるのは AB 型(またはその派生クラス)のメンバー関数だけなので、他のクラスの関数を渡すとコンパイルエラーになります。

このように、メンバー関数ポインタを活用すると、コールバック処理や戦略パターンのような設計において、クラスのメソッドを柔軟に差し替えながら型安全に扱うことができます。

  1. C++でNULLオブジェクトポインタからメンバー関数を呼び出す方法

    C++では、NULLオブジェクトポインタを使ってクラスのメンバー関数を呼び出すことができます。 注意:これは未定義動作(undefined behavior)であり、プログラムが正しく実行される保証は一切ありません。実際の結果は、使用するコンパイラによって異なります。あくまで言語仕様の理解を深めるための例としてご覧ください。 以下に、この挙動を示すサンプルプログラムを紹介します。 サンプルコード #include <iostream> using namespace std; class Demo { public : void fun() { c

  2. 【C++入門】配列を関数に渡す3つの方法をわかりやすく解説

    C++では、配列全体をそのまま関数の引数として渡すことはできません。しかし、インデックスを付けずに配列名を指定することで、配列へのポインタを渡すことができます。これは「配列名は先頭要素へのポインタに読み替えられる(配列の減衰)」というC++の仕組みによるものです。1次元配列を関数の引数として渡したい場合は、以下の3つのいずれかの方法で関数の仮引数を宣言します。どの方法でも、コンパイラに対して「整数型のポインタを受け取る」という情報が伝わるため、動作結果はすべて同じになります。配列を関数に渡す3つの宣言方法1. ポインタとして仮引数を宣言するvoid myFunction(int *param)