24

C++ で関数へのポインターを使用する際に問題があります。これが私の例です:

#include <iostream>

using namespace std;

class bar
{
public:
    void (*funcP)();
};

class foo
{
public:
    bar myBar;
    void hello(){cout << "hello" << endl;};
};

void byebye()
{
    cout << "bye" << endl;
}


int main()
{
    foo testFoo;

    testFoo.myBar.funcP = &byebye;         //OK
    testFoo.myBar.funcP = &testFoo.hello;  //ERROR
    return 0;
}

コンパイラは次の場所でエラーを返しますtestFoo.myBar.funcP = &testFoo.hello;:

ISO C++ では、バインドされたメンバー関数のアドレスを取得して、メンバー関数へのポインターを形成することを禁止しています。「&foo::こんにちは」と言う

代入で'void (foo:: )()' を 'void ( )()' に変換できません

だから私はこのようにそれを試しました:

class bar
{
public:
    void (*foo::funcP)();
};

しかし今、コンパイラはもう1つ追加します:

「foo」は宣言されていません

それを機能させる方法はありますか?

提案を事前にありがとう

4

4 に答える 4

15

みんなの提案をまとめると、最終的な解決策は次のようになります。

#include <iostream> 
using std::cout;
usind std::endl;

class foo; // tell the compiler there's a foo out there.

class bar 
{ 
public: 
    // If you want to store a pointer to each type of function you'll
    // need two different pointers here:
    void (*freeFunctionPointer)();
    void (foo::*memberFunctionPointer)();
}; 

class foo 
{ 
public: 
    bar myBar; 
    void hello(){ cout << "hello" << endl; }
}; 

void byebye() 
{ 
    cout << "bye" << endl; 
} 


int main() 
{ 
    foo testFoo; 

    testFoo.myBar.freeFunctionPointer = &byebye;
    testFoo.myBar.memberFunctionPointer = &foo::hello;

    ((testFoo).*(testFoo.myBar.memberFunctionPointer))(); // calls foo::hello()
    testFoo.myBar.freeFunctionPointer();   // calls byebye()
    return 0; 
} 

C++ FAQ Liteには、構文を単純化する方法に関するガイダンスがいくつかあります。

Chris のアイデアを取り入れて実行すると、次のようなものが得られます。

#include <iostream>
using std::cout; using std::endl;

class foo;
typedef void (*FreeFn)();
typedef void (foo::*MemberFn)();

class bar
{
public:
  bar() : freeFn(NULL), memberFn(NULL) {}
  void operator()(foo* other)
  {
    if (freeFn != NULL) { freeFn(); }
    else if (memberFn != NULL) { ((other)->*(memberFn))(); }
    else { cout << "No function attached!" << endl; }
  }

  void setFreeFn(FreeFn value) { freeFn = value; memberFn = NULL; }
  void setMemberFn(MemberFn value) { memberFn = value; freeFn = NULL; }
private:
  FreeFn freeFn;
  MemberFn memberFn;
};

class foo
{
public:
  bar myBar;
  void hello() { cout << "foo::hello()" << endl; }
  void operator()() { myBar(this); }
};

void bye() { cout << "bye()" << endl; }

int main()
{
  foo testFoo;

  testFoo();

  testFoo.myBar.setMemberFn(&foo::hello);
  testFoo();

  testFoo.myBar.setFreeFn(&bye);
  testFoo();

  return 0;
}
于 2010-03-03T21:19:33.430 に答える
10

エラーが示すように、メソッドは個々のインスタンスではなく、クラスに属します。このため、フリー関数へのポインターと非静的メソッドへのポインターはまったく別のものです。メソッドを呼び出すためのインスタンスも必要です。

//declaring and taking the address of a foo's method 
void (foo::*method)() = &foo::hello; //as the compiler nicely suggests

//calling a function through pointer
free_func();

//calling a method through pointer
foo instance;
(instance.*method)();

Boost.BindBoost.Function (std::tr1 にもあると思います)などのライブラリを使用して、違いを抽象化し、インスタンスをメソッドにバインドすることもできます。

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

using namespace std;

class foo
{
public:
    void hello(){cout << "hello" << endl;};
};

void byebye()
{
    cout << "bye" << endl;
}


int main()
{
    foo testFoo;

    boost::function<void()> helloFunc(boost::bind(&foo::hello, testFoo));
    boost::function<void()> byeFunc(byebye);

    helloFunc();
    byeFunc();
    return 0;
}
于 2010-03-03T21:02:28.173 に答える
1

2 番目のオプションを機能させるには、foo を宣言して、コンパイラがそれがクラスであることを認識できるようにします。

また、関数ポインターの構文が正しくないことに注意してください。変数の*名前の直前に来ます:

class foo;

class bar
{
public:
    void (foo::*funcP)();
};
于 2010-03-03T20:52:46.267 に答える
-1

バーの前でfooの宣言を転送します。

class foo;
于 2010-03-03T20:54:24.337 に答える