【问题标题】:How to get the function pointer of a class member in a function of the same class?如何在同一个类的函数中获取类成员的函数指针?
【发布时间】:2020-02-09 05:27:15
【问题描述】:

我对此感到困惑。 我有一个类Foo 和一个函数DoTheThing1,它接受一个指向带有0 个参数的void 函数的指针并调用该函数。

class Foo {
public:
   Foo () {}

   void DoTheThing1 (void (*theThing)()) {
      theThing();
   }
};

我有另一个类Bar,它有一个Foo 的实例。 Bar 类也有自己的函数 DoTheThing2,它尝试在其构造中将 DoTheThing2 的指针传递给 Foo's DoTheThing1

class Bar {
public:
   Foo* foo = new Foo();

   Bar () {
      foo->DoTheThing1(&Bar::DoTheThing2);
   }

   void DoTheThing2 () {
      // Something happens.
   }

};

我在传入函数指针 get 的行收到此错误error C2664: 'void Foo::DoTheThing1(void (__cdecl *)(void))': cannot convert argument 1 from 'void (__cdecl Bar::* )(void)' to 'void (__cdecl *)(void)

Bar () {
      foo->DoTheThing1(&Bar::DoTheThing2); /// Does not like.
   }

我不确定如何解决这个问题。似乎需要一些奇怪的演员表。

编辑

实际上,我的情况比仅从自身内部的类成员调用函数指针要复杂一些。我的代码实际上所做的是将指针设置为一个变量,然后再调用它。

class Foo {
public:

   void (*m_onEvent) ();

   Foo () {}

   void SetTheThing (void (*theThing)()) {
      m_onEvent = theThing;
   }

   template <typename T>
   void SetTheThing (T&& theThing) {
      m_onEvent = theThing;
   }

   void DoTheThing1 () {
      m_onEvent();
   }
};

class Bar {
public:
   Foo* foo = new Foo();

   Bar () {
      foo->SetTheThing([this](){ DoTheThing2(); });  // error C2440:  '=': cannot convert from 'T' to 'void (__cdecl *)(void)'
      foo->SetTheThing(&DoTheThing2);                // '&' illegal operation on bound member function expression.
   }

   void DoTheThing2 () {
      std::cout << "I did the thing." << std::endl;
   }

};


int main () {

   Bar* bar = new Bar();
   bar->foo->DoTheThing1();

}

编辑

所以现在我尝试使用类模板破解它,但我一直被这个错误阻止:Term does not evaluate to a function taking 0 arguments.

我正试图弄清楚我的函数指针如何不计算任何东西。

template <typename U>
class Foo {
public:


   void (U::*m_theThing) ();

   Foo () {}

   void SetTheThing (void (U::*theThing)()) {
      m_theThing = theThing;
   }

   void DoTheThing1 () {
      m_theThing(); // Term does not evaluate to a function taking 0 arguments.
   }
};

class Bar {
public:
   Foo<Bar>* foo = new Foo<Bar>();

   Bar () {
      foo->SetTheThing(&Bar::DoTheThing2);
   }

   void DoTheThing2 () {
      std::cout << "I did the thing." << std::endl;
   }
};


int main () {
   Bar* bar = new Bar();
   bar->foo->DoTheThing1();
}

【问题讨论】:

  • 函数指针和指向成员函数的指针不是一回事。一个是独立的,另一个对对象进行操作。

标签: c++ class function-pointers


【解决方案1】:

&amp;Bar::DoTheThing2 是成员函数指针,而不是常规函数指针。因此错误。这是 lambdas 和 std::functional 的解决方法:

#include <functional>

class Foo {
public:
   Foo () {}

   void DoTheThing1 (std::function<void()>& theThing) {
      theThing();
   }
};

class Bar {
public:
   Foo* foo = new Foo();

   Bar () {
      foo->DoTheThing1([this](){ DoTheThing2(); });
   }

   void DoTheThing2 () {
      // Something happens.
   }

};

如果std::functional 被证明是一个瓶颈,您可以使用模板函数:

#include <functional>

class Foo {
public:
   Foo () {}

   template <typename Callable> 
   void DoTheThing1 (Callable&& theThing) {
      theThing();
   }
};

class Bar {
public:
   Foo* foo = new Foo();

   Bar () {
      foo->DoTheThing1([this](){ DoTheThing2(); });
   }

   void DoTheThing2 () {
      // Something happens.
   }

};

编辑:

如果你想存储一个指向成员函数的指针,你还需要一个该类的实例以便以后能够调用它。以下是您可以修复示例的方法:

#include <iostream>

template <typename U>
class Foo {
public:
   void (U::*m_theThing) ();
   U* m_u;

   Foo (U* u): m_u{u} {}

   void SetTheThing (void (U::*theThing)()) {
      m_theThing = theThing;
   }

   void DoTheThing1 () {
      (m_u->*m_theThing)(); // Works fine.
   }

};

class Bar {
public:
   Foo<Bar>* foo = new Foo<Bar>(this);

   Bar () {
      foo->SetTheThing(&Bar::DoTheThing2);
   }

   void DoTheThing2 () {
      std::cout << "I did the thing." << std::endl;
   }
};


int main () {
   Bar* bar = new Bar();
   bar->foo->DoTheThing1();
}

【讨论】:

  • @GhostRavenstorm 解决了问题中的编辑问题。如果还不够清楚,请告诉我。
【解决方案2】:

旧方法:您需要一个模板来获取类和函数的特化。

工作示例:

#include <iostream>

//For member function of class C
template <typename C = void>
struct TheCaller
{
    TheCaller() : theClass(nullptr), mf(nullptr) {}
    C* theClass;
    void (C::*mf)();

    void SetTheThing(C* aClass, void (C::*memberFunction)())
    {
        theClass = aClass;
        mf = memberFunction;
    }

    void CallTheThing()
    {
        if ( theClass )
            (theClass->*mf)();
    }
};

//Specialization for any function
template <>
struct TheCaller<void>
{
    TheCaller() : mf(nullptr) {}
    void (*mf)();

    void SetTheThing(void (*memberFunction)())
    {
        mf = memberFunction;
    }

    void CallTheThing()
    {
        if ( mf )
            mf();
    }
};

struct Bar
{
    void DoTheBarThing()
    { std::cout << "DoTheBarThing called" << std::endl; }
};

void AFunction()
{ std::cout << "AFunction called" << std::endl; }

int main()
{
    TheCaller<Bar> foo;
    Bar bar;
    foo.SetTheThing(&bar, &Bar::DoTheBarThing);
    foo.CallTheThing();

    TheCaller<> foo2;
    foo2.SetTheThing(&AFunction);
    foo2.CallTheThing();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多