関数へのポインタ(一)

3620 ワード

なぜ1篇の関数のポインタの文章を書きたいのか、関数のポインタがC/C++のプログラミングの中で使う広範性に源を発して、一部の初級のプログラミング者にとって関数のポインタの使用に対して少し迷って、いったん適当な時に関数のポインタを使ったら、コードを簡潔に力があることができます.本編では,関数ポインタの基礎部分を紹介し,関数ポインタの複雑な応用を次の編で紹介する.
一般関数へのポインタ
まず関数を見てみましょう.
int Sum(int a, int b)
{
  return a + b;
}

この関数は、次のように呼び出すことができます.
Sum(1, 2);
関数のポインタを表すには、&Sumを使用するか、Sumの前のアドレスオペレータ&を削除することができます.通常の関数では、アドレスオペレータ&はオプションです.
次に、関数ポインタ変数と関数ポインタタイプについて説明します.
1.関数ポインタ変数
int (*FnName)(int, int);           //         ,   FnName         
FnName = ∑			   //  Sum        
(*FnName)(3, 5);		   //    Sum(3, 5)       

1行目には関数ポインタ変数が宣言されています.質問があれば、FnNameを新しい定義の変数として理解できます.関数ポインタ変数の宣言形式:
戻りタイプ(*関数ポインタ変数)(*パラメータリスト);
2行目はSum関数ポインタを割り当てます.注意、2つの関数ポインタパラメータタイプのみ、戻り値タイプが完全に同じでなければ値を割り当てることができません.注意修飾子const、&などが異なると、値の割り当てに失敗します.
3行目は呼び出し、呼び出し形式です.
(*関数ポインタ変数)(実パラメータリスト); 
2.関数ポインタタイプ
関数ポインタ変数の宣言について説明しましたが、関数ポインタタイプはどのように宣言しますか?関数ポインタ宣言の前にtypedefを付けると、関数ポインタタイプ定義になります.
typedef int (*FnType)(int, int);   //           
FnType fb = ∑				    //     FnType     ,   
(*fb)(3, 5);					    //     

1行目は関数ポインタのタイプを宣言し、FnTypeは新しい宣言のタイプであり、関数ポインタのタイプである.
2行目はFnTypeタイプの変数を定義し、Sum関数アドレスを割り当てます.
3行目は関数呼び出しです.関数ポインタの変数とタイプについては、次のコードを参照して理解してください.
int Sum(int a, int b)
{
  return a + b;
}

typedef int (*FnType)(int, int);
int Fun1(FnType ft, int x, int y)
{
  return (*ft)(x, y);
}
//               ,       
int Fun2(int (*fn)(int, int), int x, int y)
{
  return (*fn)(x, y);  
}

int main()
{
  cout << Fun1(&Sum, 2, 3) << " ";  //    5
  cout << Fun2(&Sum, 3, 4) << "
"; // 7 return 0; }

一般的な関数ポインタの学習はここまでにしましょう.簡単でしょう.)では、クラスのメンバー関数のポインタを学習します. 
2クラスメンバー関数を指すポインタは、まず次のクラスを見ます.
class Num
{
public:
  Num(){n_ = 0;}
  void Inc(int n);
  void Dec(int n);
  static int Sub(int a, int b);
private:
  long n_;
};

このクラスには通常のメンバー関数と静的メンバー関数があります.いずれの関数でも、関数ポインタの表現は次のとおりです.
&クラス名::関数名
Numクラスの3つのメンバー関数のポインタは、次のとおりです.
&Num::Inc;
&Num::Dec; &Num::
Sub;
1.一般メンバー関数へのポインタ
クラスメンバー関数へのポインタを宣言するときに使用します:*記号、左側はクラス名、右側はメンバー関数ポインタ名:
戻りタイプクラス名:*メンバー関数ポインタ(パラメータリスト);
呼び出すときに使用します.*または->*、左側はクラスオブジェクトの参照またはポインタ、右側はメンバー関数のポインタです.
(オブジェクト名.*メンバー関数ポインタ)(実パラメータ);
または
(オブジェクトポインタ->メンバー関数ポインタ)(実パラメータ) 
コードの例:
int main()
{
  Num obj;
  void (Num::*mf)(int);    //             mf
  mf = &Num::Inc;           //     
  (obj.*mf)(1);             //   

  //          
  typedef void (Num::*mt)(int);
  mt fn = &Num::Dec;
  (obj.*fn)(2); 

  return 0;
}

なお、Subは静的メンバー関数であり、そのポインタ宣言は非静的メンバー関数とは異なり、次に静的メンバー関数のポインタを見る. 
2.静的関数へのポインタ
int (*smf)(int a, int b); //     
smf = &Num::Sub;
cout << (*smf)(6, 7); 	   //                     

静的メンバー関数のポインタ変数、タイプ宣言は、通常の関数と一致していることがわかります. 
3.虚関数へのポインタ
コードを先に入力:
class Base{
public:
  virtual void F() const
  {
    cout << "I am the Base
"; } typedef void (Base::*FnPtr)() const; }; class Derived : public Base{ public: virtual void F() const { cout << "I am the Derived
"; } }; int main() { Base::FnPtr fp = &Base::F; Base base; (base.*fp)(); Derived derived; (derived.*fp)(); return 0; }

出力結果:
I am theBase
Iam theDerivedによると,虚関数のポインタ呼び出し結果は虚関数を直接呼び出す効果と同様であり,虚関数のポインタが指す関数アドレスはオブジェクトが動的にバインドされた関数アドレスである.