メンバ関数ポインタと多態性

http://www.geocities.jp/ky_webid/cpp/language/034.html

なお、メンバ関数ポインタが指し示しているメンバ関数が、サブクラスによってオーバーライドされており、サブクラス側のインスタンスからアクセスした場合には通常通り、多態性が働き、サブクラス側のメンバ関数が呼び出されます。

なるほど、これは試してみる価値がありそうです。

まずは仮想関数じゃない場合

#include <iostream>
using namespace std;

class CSuper {
public:
    // 仮想関数にしない
    void func () { cout << "CSuper::func" << endl; }
};

class CSub : public CSuper {
public:
    void func () { cout << "CSub::func" << endl; }
};

int main() {
    // CSuperのメンバ関数ポインタを保持
    void (CSuper::*pFunc)() = &CSuper::func;
    
    CSub obj;
    
    (obj.*pFunc)();
    return 0;
}
$ main
CSuper::func

CSuperのfuncが呼ばれました。

では次に仮想関数にして試してみます。

#include <iostream>
using namespace std;

class CSuper {
public:
    // 仮想関数に変更
    virtual void func () { cout << "CSuper::func" << endl; }
};

class CSub : public CSuper {
public:
    void func () { cout << "CSub::func" << endl; }
};

int main() {
    // CSuperのメンバ関数ポインタを保持
    void (CSuper::*pFunc)() = &CSuper::func;
    
    CSub obj;
    
    (obj.*pFunc)();
    return 0;
}
$ main
CSub::func

おお、凄い。確かに多態性が実現できてますね。素晴らしいです。

もちろんインスタンスの方をCSuperにしてもうまくいきます。

一応試してみます。

int main() {
    // CSuperのメンバ関数ポインタを保持
    void (CSuper::*pFunc)() = &CSuper::func;
    
    CSub obj;
    CSuper* p = &obj;
    
    (p->*pFunc)();
    return 0;
}
$ main
CSub::func

バッチリですね。