メンバ関数へのポインタを使って関数を呼ぶ

[戻る]
C++初心者 2004/04/08(木) 16:00:33
メンバ関数へのポインタを使って関数を呼ぶのにはどうすればいいのでしょうか?

以下がコードです。

#include <iostream>

using namespace std;

class Base
{
public:
    void(Base::*pfn)();   //  同じクラスのメンバ関数へのポインタ
    virtual void Print();
    Base() { pfn = Base::Print; }  // ここでポインタに関数をセット
};

void Base :: Print()
{
    cout << "Base::Print()" << endl;
}

int main()
{
    Base *pBase = new Base;

    (pBase->*pfn)();    //  ここでエラー

    delete pBase;

    return 0;
}

n 2004/04/08(木) 16:21:53
こうでは?
(pBase->*(pBase->pfn))();

C++初心者 2004/04/08(木) 16:29:35
ありがとうございます。
解決しましたが、また1つ問題が出ました。

上のコード、VC++6だとOKですが、BCC5.5.1だとエラーが出ます。

Base() { pfn = Base::Print; } → Base() { pfn = &Base::Print; }

とすればBCCでもOKなのですが、C++の仕様はどっちが正しいのでしょうか。
VCラウンジでする質問じゃないかもしれませんが、お願いします。

tetrapod 2004/04/08(木) 16:58:09
規格書的には、メンバ関数へのポインタを得る時には必ず & が必要です。
ISO/IEC 14882:1998 5.3.1 Unary operators 3
VC++6 の構文チェックは甘いようです。

ちなみに初期化のためには初期化構文を使うよう今から心がけておくと良いかも。

C++初心者 2004/04/08(木) 17:08:24
[[解決]]
ありがとうございます。

初期化構文とは

  Base() : pfn(&Base::Print) {}

の事でしょうか。
constオブジェクトに代入するのならともかく、それ以外では何かメリットってあるので
しょうか?

ともあれ、問題は解決しました。

tetrapod 2004/04/08(木) 17:34:40
解決済みですが一応。

初期化構文を使う=その(メンバ)オブジェクトの(引数つき)コンストラクタを使う
= で代入する=デフォルトコンストラクタで初期化した後 operator= を起動する
という重大な違いがあります。

メンバが、
単純な int やポインタであれば最適化の結果同じコードが生成されるでしょうが、
クラス型の場合は全く動作が異なります。

当該メンバがクラス型だったら初期化構文を使い、単純型 (POD) だったら使わない、
なんて区別は無駄です。だったら常に初期化構文を使うよう心がけましょう。

自分で template を書き始めるとよくわかるようになると思います。

C++初心者 2004/04/08(木) 17:52:44
ありがとうございます。


> 当該メンバがクラス型だったら初期化構文を使い、単純型 (POD) だったら使わない、
> なんて区別は無駄です。

まさに上の発想でした。
長くなるのが嫌なのが理由ですが、気をつけます。

古いスレッドには追加発言できません。