【问题标题】:Pointer to class member function指向类成员函数的指针
【发布时间】:2017-07-27 16:12:11
【问题描述】:

我有两个类,Messaging 和 GameObject。每个 GameObject 对象都有一个 Messaging 实例,我需要在 Messaging 中有一个函数指针指向 GameObject 中的一个函数。

此外,从 GameObject 派生的类中的对象也应该具有相同的属性(在其消息传递实例中具有指向其中的函数的函数指针)。

下面是代码,其中 GameCharacter 对象(从 GameObject 派生)提供要调用到其消息传递实例的函数:

messaging->Register(GameCharacter::DoMessage);

这是我的消息类代码:

/// Allows an object to send and receive messages.
class Messaging : public Component, public ::Messaging
{
private:

    // Forward declaration of GameObject
    class GameObject {};

    // Define the OnMessageType as a function pointer to a function
    // taking Message as parameter and returning void.
    typedef void (GameObject:: *OnMessageType)(Message);

    // OnMessage function pointer;
    OnMessageType OnMessage;

public:

    // Assign a function to the function pointer
    void Register(OnMessageType func) { OnMessage = func; }

    // Forward the Message to the function pointed to by the function pointer
    void DoMessage(Message msg) { (this->*OnMessage)(msg); };

};

GameObject 类:

class GameObject
{
    public:

        /// Unique number used for identification
        int id;

        /// Reference to the graphical model displayed by this object
        int modelReference;

        /// GameObject children
        std::vector<GameObject> children;

        /// Constructor
        GameObject();

        /// Destructor
        ~GameObject();

        /// Add a child GameObject node
        void AddChild(GameObject child);

        /// Update Object
        virtual void Update();

        /// Handles received messages
        //virtual void DoMessage(Message msg);

        // Provide pointers to all possible components
        Components::Transform* transform;
        Components::RigidBody* rigidBody;
        Components::Messaging* messaging;

        // Pointer to message queue
        //std::vector<Message> *msgQueue;

    private:
        /// Send message
        void SendMessage(Message msg);
};

GameObject 对象将使用 OnMessage 应该指向的函数调用 Register。然后当调用 DoMessage 时,应该调用 GameObject 中指向的函数。因此,在这种情况下,调用 DoMessage(在 GameCharacter 的消息传递实例中)应该依次调用 GameCharacter 对象中的 DoMessage。

问题是我在 DoMessage(Message msg) 函数上收到此错误:

指向成员类型'void的指针 (Components::Messaging::GameObject::)(Message)' 与 对象类型'Components::Messaging'

据我所知,它对指针函数类型的不满。我已经读过(在堆栈溢出帖子上),在调用指针函数时,应该指定成员函数所属的类型,但我找不到如何做到这一点......

任何人都可以对此有所了解并解释我如何修复我的代码吗?

【问题讨论】:

  • 请发布 GameObject 类。 GameCharacter::DoMessage 是静态函数吗?
  • 为什么不用EntityX或者anax组件系统库?
  • 不,在 GameCharacter 类中它是一个私有成员函数。

标签: c++ class pointers


【解决方案1】:

std::functionstd::bind 一起使用,而不是函数指针。您收到此类错误的原因是您没有对象来接收函数调用,但您只有一个函数。如果需要通过指针调用成员函数,则必须保留两件事:

  1. 函数指针
  2. 您保留了成员函数指针的类的对象

实现您想要的最佳方式是将std::functionstd::bind 结合使用。示例:

using namespace std::placeholders;
GameCharacter gameCharacter;
messaging->Register(std::bind(GameCharacter::DoMessage, gameCharacter, _1));

并且Messaging 类必须接受std::function&lt;void(Message)&gt; 对象类型。

class Messaging : public Component, public ::Messaging
{
private:

    // Forward declaration of GameObject
    class GameObject {};

    // Define the OnMessageType as a function pointer to a function
    // taking Message as parameter and returning void.
    //typedef void (GameObject:: *OnMessageType)(Message);
    typedef std::function<void(Message)> OnMessageType;

    // OnMessage function pointer;
    OnMessageType OnMessage;

public:

    // Assign a function to the function pointer
    void Register(OnMessageType func) { OnMessage = func; }

    // Forward the Message to the function pointed to by the function pointer
    void DoMessage(Message msg) { this->OnMessage(msg); };

};

【讨论】:

  • 实现此功能的even better 最佳方法是使用捕获GameCharacter 对象而不是std::bind 的lambda。
  • @Jarod42:这似乎有效,但现在消息传递->Register(GameCharacter::DoMessage) 抱怨:“没有匹配函数调用'Components::Messaging::Register()'" 知道为什么吗?必须说我在这里超出了我的深度,必须阅读。
  • @fnc12:这看起来是一个干净的解决方案,但目前我无法让 Eclipse 识别 std::function。我已包含 但仍然找不到它。认为我需要先启用 c++11...
  • @fnc12:我让 Eclipse 能够识别 std::function 并且代码现在可以正常编译,但是在运行时会崩溃...我会慢慢地再一遍一遍...
  • 它现在可以工作了!谢谢!崩溃是由于没有正确思考并在 GameObject 构造函数中创建 gameObject 对象造成的 :-) 目前我正在试验一个基本的游戏引擎,你可能已经猜到这是消息系统实现的一部分。
【解决方案2】:

Messaging 不继承自GameObject,因此您不能使用this 实例调用OnMessage

你需要一个GameObject的实例来调用成员方法。

 GameObject gameObject;

 (gameObject.*OnMessage)(msg);
 // or (gameObject.*this->OnMessage)(msg);

但不确定这是你想要做的。

也许你真的想要std::function&lt;void(Message )&gt;...

【讨论】:

  • @Quentin:错字,我不想使用演员表,只需使用我之前定义的实例即可。现已修复。
  • 你确定这可以编译吗? OnMessage 不是GameObject 类的成员(但属于Messaging 类)。
  • @Quentin:代码应该在你的“修复”之前工作。而我的明确表示OnMessage 是会员。
  • @Jarod42 哦,我的错!我在那里混合了运算符优先级,认为gameObject.*this 将首先被绑定(因此失败)。对不起!
猜你喜欢
  • 2013-06-06
  • 1970-01-01
  • 2015-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多