C/C++の特徴の一つにポインタが使えるという点がありますが,
たまに使い方を忘れちゃう時があります.
昔のソースを引っ張り出すのも面倒なので,ここにまとめておきます.

変数へのポインタ(C/C++)

これは基本ですね.あまり説明は必要ないでしょう.
ポインタ変数に変数のアドレスを代入し,そのアドレスを経由して元の変数を操作する事ができます.
また,関数へ構造体のようなサイズの大きな変数を渡す時に,
構造体へのポインタを関数に渡すと,関数呼び出しの際に構造体のコピーが作られないので,
呼び出しに必要な時間を短縮する事ができたりします.

サンプル

    int Num=10;
    int *pn=&Num;
    *pn=3;
    
    char Str[]="sakana soyosoyo";
    char *Str2=Str;
    Str2+=7;
    printf("Num:%d\tStr2:%s\n", Num, Str2);

こんな風に使います*1
関数の引数に使う事が一番多いかと思います.後は,mallocやnewの返り値を覚えるのにもよく使いますね

関数ポインタ(C/C++)

関数ポインタはその名の通り関数へのポインタです.
慣れてくると強力な事に気づくと思います.

サンプル

#include <stdio.h>

//関数ら
int plus(int a, int b)    {return a+b;}
int minus(int a, int b)    {return a-b;}
int multi(int a, int b)    {return a*b;}
int div(int a, int b)    {return a/b;}

//関数ポインタの配列
int (*Calc[])(int a, int b)={
    plus, minus, multi, div
};

void main()
{
    int a, b;
    int ret;

    printf("二つの数字を入力してください\n(a b):");
    scanf("%d %d", &a, &b);
    printf(
        "何をしますか?\n\
        0:足し算\n\
        1:引き算\n\
        2:掛け算\n\
        3:割り算\n?:"
    );
    scanf("%d", &ret);
    
    //関数ポインタから関数を呼び出す
    if(ret<4)
        printf("Result:%d\n", 
            Calc[ret](a, b) ); 
    else
        printf("error!\n");
}

関数ポインタを利用すると

Calc[ret](a, b);

のように比較無しに呼び出す関数を選択する事ができるのが分かると思います.
関数ポインタを使わないと関数の呼び分けが

    switch(ret)
    {
    case 0:
        ret=plus(a, b);
        break;
    case 1:
        ret=minus(a, b);
        break;
    case 2:
        ret=multi(a, b);
        break;
    case 3:
        ret=div(a, b);
        break;

    }
    printf("Result:%d\n", ret);

な風になってしまいます.

おまけ

毎回毎回

int (*Calc)(int a, int b);

のように書くのはめんどくさいのですが,

typedef int CALC(int a, int b);

のように,typedefを使うと

 CALC *Calc;

だけで関数ポインタを宣言できます.

メンバポインタ(C++)

C++から追加された新しいポインタです.「.*」,「->*」等のCには無かった演算子を使います.
また,メンバポインタ自体は

int Class::*mp;

のように宣言します. このポインタは,クラスからメンバ変数への相対的な位置の(ような)アドレスが入っています.
複数のクラスの同じメンバ変数にアクセスしたい時に使います.*2
説明を読んでもよく分からないと思うのでサンプルを見てみましょう

サンプル

#include <stdio.h>

class MAN
{
public:
    int v1;
    int v2;
    MAN(int a, int b){v1=a; v2=b;}
};

void main()
{
    int MAN::*mp;    //メンバポインタ
    MAN man(1, 2);
    MAN man2(3, 4);
    //メンバポインタに相対的なアドレスをコピー
    mp=&MAN::v1; //&man::v1ではエラーです
    //メンバポインタを使ってメンバ変数にアクセス
    printf("man:%d    man2:%d\n", man.*mp, man2.*mp);
    
    mp=&MAN::v2;
    printf("man:%d    man2:%d\n", man.*mp, man.*mp);
}
  • 実行結果
    man.*mp:1
    man.*mp:2

メンバ関数ポインタ(C++)

メンバポインタの関数版です.

サンプル

#include <iostream>
using namespace std;
class MAN
{
public:
    void func1(){cout << "func1"<<endl;}
    void func2(){cout << "func2"<<endl;}
};

void main()
{
    void (MAN::*mp)();    //メンバ関数ポインタ
    MAN man;
    MAN man2;

    //メンバ関数ポインタに相対的なアドレスをコピー
    mp=MAN::func1;
    //メンバ関数ポインタを使ってメンバ関数を呼ぶ
    //一つのポインタで複数のクラスの同じメンバ関数を呼ぶ事ができる
    (man.*mp)(); //man.*mp() や man.(*mp)()ではエラーです カッコの位置に注意
    (man2.*mp)();
    
    mp=MAN::func2;
    (man.*mp)();
    (man2.*mp)();
}

コメント欄

あまり細かく書いてないので,分かりにくいかもしれません.*3
分からなかった所は質問していただければ分かる範囲でお答えします.

  • メンバ関数ポインタの初期化が違ってますね -- 2013-10-04 16:26:46 (金)

お名前:

*1 いや,使わないですね(^^;
*2 普通のポインタでは出来ません
*3 私が思い出すのに必要な程度の事しか書いてないです