将成员函数指针传递给c++中的成员对象

发布于 2024-08-23 12:17:47 字数 941 浏览 1 评论 0原文

我在 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::hello'

无法在赋值中将“void (foo::)()”转换为“void ()()”

所以我像这样尝试过:

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

但现在编译器又添加了一个:

“foo”尚未声明

有办法让它工作吗?

预先感谢您的建议

I have a problem with using a pointer to function in C++. Here is my example:

#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;
}

Compilator returns an error at testFoo.myBar.funcP = &testFoo.hello;:

ISO C++ forbids taking the address of a bound member function to form a
pointer to member function. Say
'&foo::hello'

cannot convert 'void (foo::)()' to 'void ()()' in assignment

So i tried it like this:

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

But now the compilator adds one more:

'foo' has not been declared

Is there a way make it work?

Thanks in advance for suggestions

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无人问我粥可暖 2024-08-30 12:17:48

正如错误所述,方法属于类,而不属于单个实例。因此,指向自由函数的指针和指向非静态方法的指针是完全不同的东西。您还需要一个实例来调用该方法。

//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;
}

As the error says, methods belong to the class, not to individual instances. For this reason pointers to free functions and pointers to non-static methods are completely different things. You'll also need an instance to call the method on.

//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)();

You can use libraries like Boost.Bind and Boost.Function (also in std::tr1 I think) to abstract away the difference and also bind an instance to the method:

#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;
}
豆芽 2024-08-30 12:17:48

要使第二个选项起作用,请声明 foo 以便编译器知道它是一个类。

另请注意,您的函数指针语法不正确。 * 位于变量名称之前:

class foo;

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

To make your second option work, declare foo so the compiler knows that it is a class.

Also note that your function pointer syntax is incorrect. The * comes just before the name of the variable:

class foo;

class bar
{
public:
    void (foo::*funcP)();
};
柠檬色的秋千 2024-08-30 12:17:48

将 foo 的声明转发到 bar 前面:

class foo;

forward foo's declaration in front of bar:

class foo;
乱世争霸 2024-08-30 12:17:47

综合大家的建议,您的最终解决方案将如下所示:

#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 有一些关于如何简化语法的指导。

采纳克里斯的想法并付诸实践,你可以得到这样的结果:

#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;
}

Taking everyone's suggestions together, your final solution will look like:

#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; 
} 

The C++ FAQ Lite has some guidance on how to simplify the syntax.

Taking Chris' idea and running with it, you could get yourself something like this:

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文