C++ のメンバー関数への関数ポインタ

Jay Shaw 2023年10月12日
  1. C++ でメンバー関数への関数ポインタを実装する
  2. C++ のメンバー関数にポインターを付加する
  3. C++ でポインターシンボルを使用せずにメンバー関数へのポインターを呼び出す
  4. C++ の関数ポインタと同じクラスのメソッドを指定する
  5. C++ で文字列コマンドを使用したメンバー関数への関数ポインタ
C++ のメンバー関数への関数ポインタ

変数がプログラミング言語で作成される場合、マシンはその値をコンピュータのメモリに保存する必要があります。マシンは、空であるかどうかに関係なく、この変数にいくらかのメモリを割り当てます。

多くの場合、変数の値の代わりに場所が必要になります。その間、これらの値はポインタを介してフェッチできます。

さらに、C++ のポインタを使用して、メモリアドレスを参照する場合と比較して、関数などのコードを指すこともできます。これらは関数ポインタと呼ばれ、コードの効率を高めます。

この記事の例では、クラス内で関数ポインターを使用して、ポインターが C++ のメンバー関数を指すようにする方法を明確に示します。

C++ でメンバー関数への関数ポインタを実装する

これを行うには 2つの方法があります。

  1. メンバー関数を指す関数ポインターが作成されます。
  2. 関数ポインタの名前だけを使用してメソッドを呼び出す。

C++ のメンバー関数にポインターを付加する

ポインタ関数を使用するには、次の手順が必要です。

  1. 戻り型が void のパラメーター化された関数。
  2. ポインター変数のキャストと入力します。
  3. ポインタ変数をメソッドに割り当てます。
  4. ポインタを使用して main 関数内のパラメータ化された関数を呼び出すメソッド呼び出し。

標準の stdio パッケージは、プログラム内の入出力機能用にインポートされます。関数 display は、整数データ型のパラメーターvar1 で宣言されています。

void display(int var1) { printf("The variable holds value = %d\n", var1); }

display メソッド内に、var1 が出力されます。

変数 ptr_method には、main 関数内に void のデータ型があります。void は c++ のデータ型として使用できますが、プレースホルダーとして機能し、データの種類を正確に表すものではないことに注意する必要があります。

宣言されたポインタ変数には、次のような整数パラメータが提供されます。

void (*ptr_method)(int)

ptr_method には整数パラメータがあります。これにより、ptr_method の呼び出し中にメンバーメソッドに値が渡されます。

他のデータ型を使用するとコンパイラで誤った変換エラーが発生するため、ポインタ関数 ptr_method には void データ型が指定されています。

関数ポインタは、以下の構文を使用して、プログラムの開始時に宣言された関数に割り当てられます。次の構文を使用して、関数 display へのポインタポイントを作成します。

ptr_method = &display;

最後に、ポインタ関数は、"65"として提供される整数パラメータを使用して呼び出されます。

コード:

#include <stdio.h>

// This method has a parameter int and a return type which is void

void display(int var1) { printf("The variable holds value = %d\n", var1); }

int main() {
  void (*ptr_method)(int);
  ptr_method = &display;

  (*ptr_method)(65);

  return 0;
}

出力:

The variable holds value = 65

C++ でポインターシンボルを使用せずにメンバー関数へのポインターを呼び出す

この例で使用されているプログラムは、関数呼び出しを除いて上記のプログラムと同じです。ここで、ポインタ変数は、アスタリスク記号(*)を除いて、変数の名前を使用して呼び出されます。

関数ポインタがメソッドに向けられると、その中に格納されているメソッドのメモリアドレスに、ポインタと変数形式の両方を使用してアクセスできるため、プログラムは意図したとおりに機能します。たとえば、関数ポインタ ptr_method が定義されている場合、関数 display の割り当ては、前の例のように変数名の前に&を追加するのではなく、変数名を直接利用することによって実行されます。

関数呼び出しでは、関数ポインターptr_method がポインター記号(*)なしで直接呼び出され、値 54 が渡されます。

void (*ptr_method)(int);
ptr_method = display;

ptr_method(54);

コード:

#include <stdio.h>

void display(int var1) { printf("The variable holds value = %d\n", var1); }

int main() {
  void (*ptr_method)(int);
  ptr_method = display;

  ptr_method(54);

  return 0;
}

出力:

The variable holds value = 54

C++ の関数ポインタと同じクラスのメソッドを指定する

この例で使用されているプログラムは、他の 2つのプログラムと同様です。ただし、ここでは、ポインターはメソッドですが、作業は他の 2つのプログラムの単純なポインター変数によって処理されました。

コンストラクタークラス assgnPtr は、2つのパブリックメンバー(char メソッド foo と関数ポインターptr である別の char メソッド)で作成されます。2つのメソッドは、以下の構文に示されています。構文の最後の行から、関数ポインターのクラス assgnPtr を指していることがわかります。

public:
char foo();
char (assgnPtr::*ptr)();

パブリックメソッドが宣言された後、関数 foo() に戻り値 f が提供されます。これは、関数ポインタが呼び出されると、プログラムが関数 foo を呼び出し、返されたものをすべて出力することを意味します。

var1 という名前の変数が main メソッド内で宣言されています。この変数はクラスオブジェクトとして機能します。

これは、メンバー関数である関数ポインタには、同じクラスのオブジェクトがないとアクセスできないという欠点があるためです。メンバー関数は、次の構文でポインター変数に割り当てられます。

int main() {
  assgnPtr var1;
  var1.ptr = &assgnPtr::foo;

ポインタ ptr はオブジェクトクラス var1 と一緒に使用され、メソッド foo が割り当てられます。コンストラクターとして、メソッドは::シンボルを使用して割り当てる必要があります。これは、関数がクラス assgnPrt のメンバーメソッドであることを示します。

最後に、結果を印刷する必要があります。

printf("%c\n", (var1.*(var1.ptr))());

理解するのは非常に複雑なので、読者にとっては厄介なことかもしれません。したがって、明確に理解するには、ビットに分割する必要があります。

var1.ptr は、クラス assgnPtr のメンバー関数へのポインタです。ただし、var1.ptr)を使用すると、var1.ptr)を出力するときにポインタ参照になります。これは、ptr がスコープ内にないためです。

そのため、クラスオブジェクト var1var1.*(var1.ptr) としてバインドする必要があります。

最後に、(var1.*(var1.ptr))() は引数なしでメソッドを呼び出します。print ステートメントは、関数ポインターを使用してメソッドが呼び出されたときに返される値を出力します。

完全なソースコード:

#include <iostream>

class assgnPtr {
 public:
  char foo();
  char (assgnPtr::*ptr)();
};

char assgnPtr::foo() { return 'f'; }

int main() {
  assgnPtr var1;
  var1.ptr = &assgnPtr::foo;
  printf("%c\n", (var1.*(var1.ptr))());
}

出力:

f

C++ で文字列コマンドを使用したメンバー関数への関数ポインタ

この例では、プログラムは文字列コマンドを使用して関数ポインタを割り当てます。メンバーメソッドが関係演算子を使用してポインタをチェックして割り当てることを除いて、コアの概念は似ています。

このプログラムは、i/o 用の iostream と文字列コマンド用の string の 2つのインポート関数を使用します。コンストラクタークラス assgnPtr2 が作成されます。

2つのプライベートメンバーdisplaypass_value とパブリックメンバーfunc_ptr があり、これらは関数ポインタになります。

プライベートメンバーpass_value には、データ型文字列の変数 x と y、および関数プロトタイプ foo の 3つのパラメーターがあります。関数プロトタイプは、パラメーターfoo が関数へのポインターになると述べています。

メソッド display は、ポインタが割り当てられるとステートメントを出力します。メソッド func_ptr はメソッド pass_value を呼び出し、xy の値をパラメーターとして渡し、関数プロトタイプの引数として&記号を使用してメソッド display をアタッチします。

最後に、メソッド pass_value 内で、渡された x と y の値が、関係演算子 == を使用して比較されます。x と y の両方の値が一致する場合、if ステートメントはポインターfoo をメソッドに割り当てます。

main 関数内に、クラスオブジェクト var が作成されます。このオブジェクトを使用して、メソッド func_ptr が呼び出されます。

完全なソースコード:

#include <iostream>
#include <string>

class assgnPtr2 {
 public:
  void func_ptr();

 private:
  void display();
  void pass_value(std::string x, std::string y, void (assgnPtr2::*foo)());
};

void assgnPtr2::display() { std::cout << "Pointer Assigned\n"; }

void assgnPtr2::func_ptr() { pass_value("h", "h", &assgnPtr2::display); }

void assgnPtr2::pass_value(std::string x, std::string y,
                           void (assgnPtr2::*foo)()) {
  if (x == y) {
    (this->*foo)();
  }
}

int main() {
  assgnPtr2 var;
  var.func_ptr();
  return 0;
}

出力:

Pointer Assigned

関連記事 - C++ Pointer