GCCを使用してプログラミングをしています。C++のメンバ関数をメモリに保存し、呼び出す方法を試しています。リンク先に記載させていただいたサンプコードとコンパイル手順にて調査を行っておりますが、エラーを回避することができていない状況です。


http://d.hatena.ne.jp/j884/20110409

URLの紹介だけではなく、先にあげたサンプルコードでの具体的な実装方法をご助言いただけますとうれしいです。

[環境]
Windows Vista
MinGW-5.1.6

回答の条件
  • 1人2回まで
  • 13歳以上
  • 登録:2011/04/10 01:29:24
  • 終了:2011/04/10 22:03:43

ベストアンサー

id:tdoi No.2

tdoi回答回数174ベストアンサー獲得回数752011/04/10 08:29:31

ポイント65pt

こんな方法でいいのでしょうか?

1.正しい型の変数を用意する。

エラーの通り、関数ポインタの型が違います。

スタティックではないメンバ関数は、インスタンス無しでは呼び出すことはできませんので、型が違いますし、呼び出し方も違います。

参考

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

// 引数なしのmyclassのメンバ関数に対する関数ポインタを定義
void (myclass::*func)() = 0;

int main() {
  myclass c;


  // 関数ポインタにmyclass::fooをセット
  func = &myclass::foo;

  // インスタンスcに対して、funcにセットしたメンバ関数を呼び出す。
  (c.*func)();
}

2.boostを使う

1の方法は正しいですが、引数なしで戻り値がない関数なのに、型を変えて統一的に扱うことが難しいです。そんなときは可能であれば、boostの導入を検討してみてください。ただし、以下の例では、funcはグローバルに定義していますが、オブジェクトcの生存しているうちに呼び出さないと、セグメンテーションエラーを起こしますので、注意してください。その際は、shared_ptrなどを併用してください。

#include <boost/function.hpp>
#include <boost/bind.hpp>

// 引数なしの戻り値がvoidのファクタfuncを定義
boost::function0<void> func;

int main() {
  myclass c;

  // インスタンスcに対するfooの呼び出しを行うファクタをfuncにセット
  func = boost::bind(&myclass::foo, &c);

  // ファンクタの実行
  func();
}

3.foo自体をstaticにしてしまう

1と2は元のmyclassの定義に影響を与えないという前提で対処していますが、myclassに変更を加えてもよいのであれば、fooをstaticにしてしまうという方法もあります。ただし、この方法では、valueにアクセスできません。

class myclass
{
public:
  myclass() {}
  // 関数fooをstaticとして定義
  static void foo() {
    printf("myclass::foo");
  }
};

// 引数なし戻り値voidの関数ポインタfuncを定義
void (*func)() = 0;

int main() {
  // myclassのfooをfuncにセット
  func = &myclass::foo;
  // funcにセットした関数を呼び出し
  (*func)();
}

何かの参考になれば。

id:j884

大変参考になりました。ありがとうございます。

2011/04/10 22:01:48

その他の回答(1件)

id:asuka645 No.1

あすか回答回数856ベストアンサー獲得回数972011/04/10 08:04:17

ポイント5pt

ご質問のソースの意図がよく分からないのですが、下記のようにすれば目的の結果は得られると思います。

#include <stdio.h>

void (*func)() = 0;

class myclass {
    public:
    void foo();
    int value;
};

void myclass::foo() {
    printf("myclass::foo i = %d\n", value);
}

int main() {
    puts("main");
    myclass c;
    c.value = 5;
    c.foo();
}
id:j884

ご説明が不十分でした。関数をポインタに保存しそれをコールする、コールバック関数のような用途を意図したものでした。

2011/04/10 10:05:32
id:tdoi No.2

tdoi回答回数174ベストアンサー獲得回数752011/04/10 08:29:31ここでベストアンサー

ポイント65pt

こんな方法でいいのでしょうか?

1.正しい型の変数を用意する。

エラーの通り、関数ポインタの型が違います。

スタティックではないメンバ関数は、インスタンス無しでは呼び出すことはできませんので、型が違いますし、呼び出し方も違います。

参考

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

// 引数なしのmyclassのメンバ関数に対する関数ポインタを定義
void (myclass::*func)() = 0;

int main() {
  myclass c;


  // 関数ポインタにmyclass::fooをセット
  func = &myclass::foo;

  // インスタンスcに対して、funcにセットしたメンバ関数を呼び出す。
  (c.*func)();
}

2.boostを使う

1の方法は正しいですが、引数なしで戻り値がない関数なのに、型を変えて統一的に扱うことが難しいです。そんなときは可能であれば、boostの導入を検討してみてください。ただし、以下の例では、funcはグローバルに定義していますが、オブジェクトcの生存しているうちに呼び出さないと、セグメンテーションエラーを起こしますので、注意してください。その際は、shared_ptrなどを併用してください。

#include <boost/function.hpp>
#include <boost/bind.hpp>

// 引数なしの戻り値がvoidのファクタfuncを定義
boost::function0<void> func;

int main() {
  myclass c;

  // インスタンスcに対するfooの呼び出しを行うファクタをfuncにセット
  func = boost::bind(&myclass::foo, &c);

  // ファンクタの実行
  func();
}

3.foo自体をstaticにしてしまう

1と2は元のmyclassの定義に影響を与えないという前提で対処していますが、myclassに変更を加えてもよいのであれば、fooをstaticにしてしまうという方法もあります。ただし、この方法では、valueにアクセスできません。

class myclass
{
public:
  myclass() {}
  // 関数fooをstaticとして定義
  static void foo() {
    printf("myclass::foo");
  }
};

// 引数なし戻り値voidの関数ポインタfuncを定義
void (*func)() = 0;

int main() {
  // myclassのfooをfuncにセット
  func = &myclass::foo;
  // funcにセットした関数を呼び出し
  (*func)();
}

何かの参考になれば。

id:j884

大変参考になりました。ありがとうございます。

2011/04/10 22:01:48

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません