ページ 11

C++でのメンバ関数ポインタの扱い方について

Posted: 2010年3月19日(金) 23:16
by ぬっち
こんばんは。
今回は、C++でのメンバ関数のポインタについて困ったことがあったのでここで質問させていただきます。

C++でメンバ関数のポインタをメンバ変数に以下のように最初に代入しました。
namespace Foo
{
    class hoge
    {
        //...(略)
        bool ( hoge::*m_phogeFunc )();
    public:
        //...(略)
        bool hogeFunc();
        void start();
    };

    //コンストラクタ
    hoge::hoge()
    {
        m_phogeFunc = &hoge::hogeFunc;
    }

    void hoge::start()
    {
        loop( m_phogeFunc )
    }
}
また、startという関数でグローバルスコープの関数ポインタを引数に取るloopという関数を呼び出すことにします。
すると、loopの引数をFoo::hoge::*から*に変換できませんと出てコンパイルエラーとなります。

スコープの違いで出るエラーだと思うのですが・・・。
これを解決する手段はないのでしょうか?

Re:C++でのメンバ関数ポインタの扱い方について

Posted: 2010年3月20日(土) 00:22
by たかぎ
> スコープの違いで出るエラーだと思うのですが・・・。

違います。
loop関数の仕様が不明なので正確なことはいえませんが、非静的メンバ関数へのポインタと通常の関数へのポインタの間には互換性がありません。
暗黙的にthisに相当する情報を渡す/渡さないの違いだけを考えても、そのあたりは理解できるはずです。

Re:C++でのメンバ関数ポインタの扱い方について

Posted: 2010年3月20日(土) 08:38
by ぬっち
返信ありがとうございます。

>非静的メンバ関数へのポインタと通常の関数へのポインタの間には互換性がありません。
なるほど、つまりオブジェクトの実体が存在するかがわからないので問題があり、staticにすることによって、プログラム開始時に実体が生成されるため問題が起こらないということでしょうか?

そうなると、やはり無理そうですね。

Re:C++でのメンバ関数ポインタの扱い方について

Posted: 2010年3月20日(土) 09:04
by たいちう
> そうなると、やはり無理そうですね。

何をしたいのかが私には伝わってこないので、
無理かどうか判断できません。

背景等も含め、やりたいことを整理して説明してみませんか。

Re:C++でのメンバ関数ポインタの扱い方について

Posted: 2010年3月20日(土) 19:15
by ぬっち
返信ありがとうございます。

実は自作のDirectXのライブラリの中でloopという関数があり、その関数に関数ポインタを渡すことにより、渡した関数ポインタの関数がメインループとして使われるという仕様になっています。
例:
loop( draw );
この時はdraw関数がメインループとして使用されます。
つまり、draw関数内に記述したものがループする仕組みになっています。

この自作のDirectXのライブラリは基本的にC言語だけの知識で使えるということを目標にしていました。(つまり、DXライブラリのような感じです。)
そのため、C++で使われることを前提に作成していませんでした。
そして今回クラスのメソッド内にある起動関数で、同じクラスにある描画関数のポインタを先ほどの関数loopに渡して呼び出すことにしようと思ってたらエラーが出たわけです。

最終的にはC++用のライブラリを作成しようと思っているのですが、C用に作ったライブラリで今回は作成して見ようと考えたわけです。
最悪の場合、メインループ処理の部分をクラス化しないでプログラムを書こうと思っています。

Re:C++でのメンバ関数ポインタの扱い方について

Posted: 2010年3月23日(火) 13:35
by たいちう
時間が空いてしまったので、もう見てないかもしれませんが、
このような事がしたかったのでしょうか?
#include <iostream>

typedef void (*PFUNC)();

void loop(PFUNC f) {
    for (int i = 0; i < 5; i++)
        f();
}

class hoge {
    static void draw() {
        std::cout << "hoge::draw!" << std::endl;
    }
    PFUNC func_;
public:
    hoge() {
        func_ = draw;
    }
    void start() {
        loop(func_);
    }
};

int main() {
    hoge h;
    h.start();

    return 0;
}

Re:C++でのメンバ関数ポインタの扱い方について

Posted: 2010年3月25日(木) 20:37
by ぬっち
返答ありがとうございます。

まさにたいちうさんがおっしゃったことをしたかったのです。
やはりdraw関数はstaticにする必要があるみたいですね。

あの後loop部分を完全に書き換え、関数ポインタを使わずにC言語だけでのライブラリを作成することに成功しまして、問題となっていたクラスを使っての方法も実現することができました。

いろいろ勉強になりました。ありがとうとうございます。
今後もよろしくお願いします^^