C ++非成员访问成员函数

时间:2014-06-09 01:38:47

标签: c++ oop

我正在与一个项目的另一个团队合作。另一个团队正在构建一个GUI,与大多数GUI框架一样,它是非常继承的。另一方面,这方面的代码(“我猜可以说是'底端')基本上是C(尽管我认为它在技术上都是通过MSVC2010工具链的C ++而不是”视为C“标志。

两个模块(UI和this)必须单独编译,然后链接在一起。

问题: 需要为底端弹出一个需要在GUI端调用重绘功能并给它一些数据。现在这里的事情变得糟糕。如何调用INTO一组成员函数,尤其是一个复杂的依赖项?如果我尝试包含窗口标题,那么一个英里长的GUI内容就有一个继承列表,底层显然不是针对复杂的GUI库构建的......我无法转发声明我的出路,因为我需要在窗口上调用一个函数?

现在显然这是一个主要的通信设计缺陷,尽管我们目前处于不利地位,而重大重组并非真正的选择。

问题:

  1. 如何组织底部联系顶部进行重绘,从C代码球到C ++节点球。

  2. 我现在可以做些什么来规避这个问题?

  3. 我能想到的唯一好方法是使用某种通信类......但我不知道它是如何不会遇到同样的问题因为它需要针对GUI和底端?

1 个答案:

答案 0 :(得分:0)

如果您只需要调用单个函数,甚至是一小部分函数,​​回调可能是您最好的选择。如果您正在处理成员函数,您仍然可以使用指向成员函数的指针和指向相关对象的指针来调用它。请参阅this answer for details on doing that.但是,这可能意味着要求您为GUI代码包含整个一英里长的依赖项列表。

编辑:经过一番思考后,您可以对一些函数进行回调,而无需包含GUI代码的依赖项。例如:

在某处的GUI代码中......

int DoFooInBar(int arg1, const char *arg2){
    return MyForm.ChildContainer.ChildBox.ChildButton.Bar.DoFoo( arg1, arg2 );
}

现在在GUICallbacks.hpp ...

int DoFooInBar(int arg1, const char *arg2);

然后,您可以在C代码的任何位置加入GUICallbacks.hpp并致电DoFooInBar()。此方法的唯一问题是您需要为要使用的每个回调创建一个新函数。

批量完成此类任务的更通用方法是通过传递消息。正如您所提到的,一种非常跨平台的方法涉及通信对象。如果您提供了一种通过命名机制获取指向共享通信对象的指针的机制,则您不一定会遇到任何构建问题。一个小例子是:

class CommObj{
public:
    struct Message{
        uint32_t type;
        uint32_t flags;
        std::string title;
        std::string contents;
        ... //maybe a union here or something instead
    };
private:
    static map<std::string, CommObj*> InternalObjects;
    std::deque<Message> Messages;
    std::string MyName;
public:
    CommObj(const char *name); //Registers the object in the map
    ~CommObj(); //Unregisters the object in the map
    void PushMessage( uint32_t type, uint32_t flags, const char *title, const char *contents, ...);
    Message GetMessage();
    bool HasMessages();
    static CommObj *GetObjByName(const char *name);
    static bool ObjWithNameExists();
};

显然你可以制作更像C的版本,但是为了清晰起见,这是用C ++编写的。实施细节是读者的练习。

使用此代码,您可以简单地构建针对此对象的后端和前端,并且可以对代码的两端运行检查以查看是否已创建名为"Backend->GUI"的CommObj 。如果没有,那就去吧。然后,您可以通过使用GetObjByName("Backend->GUI");抓取指向它的指针开始与此对象通信。然后,您将连续轮询对象以查看是否有任何新消息。您可以使用GUI的另一个对象将消息发布到后端,也许命名为"GUI->Backend",或者您可以在对象本身中构建双向性。

另一种方法是使用套接字通信/共享文件描述符。然后,您可以读取数据并将数据写入套接字,以便另一方接收。对于基本信号,这可能是一种简单的方法来完成您的需要,特别是如果您真的不需要任何复杂的东西。对套接字描述符的简单send()调用将是您发送代码另一端所需的全部信息。

请注意,使用套接字如果使用得非常严重,可能会导致速度减慢。它取决于底层实现,但localhost上的套接字通常比原始函数调用慢。你可能不会在紧密循环中需要互锁信号,所以你应该对任何一种方法都没问题。当我说慢一点时,我的意思是它可能是50微秒而不是5微秒。对于大多数情况来说,并没有太多担心,但需要注意的事项。另一方面,如果GUI代码在与后端代码不同的线程中运行,您可能希望在发布/读取消息之前互斥通信对象,这对于共享文件描述符是不需要的。互斥/信号量带来自己的行李处理。

使用像我给出的大纲那样的通信对象将允许你可能感兴趣的一些类型的自动编组。当然,你也可以编写一个对象来用套接字进行编组,但是在你不妨使用共享对象。

我希望你的项目顺利进行。