使用C ++中的方法更新外部结构

时间:2019-02-26 16:18:24

标签: c++

我目前正在通过automatak使用opendnp3软件包。 https://github.com/automatak/dnp3/blob/2.0.x/cpp/examples/outstation/main.cpp

我无法理解的是如何在Struct(超出类范围的定义)中更新信息,而不将结构传递给类(我认为我不能作为我的代码来做)从未真正调用过该方法,因此我无法更改调用该方法时传递给该方法的内容。

继承图:

我已经通过创建自己的类(MyCommandHandler)覆盖了SimpleCommandHandler类中的虚拟方法DoOperate。 DoOperate函数提供的所有功能均由asio提供。

struct State
{
    double value0 = 0;
    double value1 = 0;
    bool binary0 = false;
    bool binary1 = false;

};

State state;

class MyCommandHandler : public SimpleCommandHandler
{
public:

    static std::shared_ptr<ICommandHandler> Create()
    {
        return std::make_shared<MyCommandHandler>();
    }

    MyCommandHandler() : SimpleCommandHandler(CommandStatus::SUCCESS) {}

protected:

    void DoOperate(const ControlRelayOutputBlock& command, uint16_t index, OperateType opType) {

            ////*** This is where I need to update the Struct ***////
            ////    state.value0 = 30;                           ////
            ////    state.value1 = 30;                           ////
            ////    state.binary0 = true;                        ////
            ////    state.binary1 = true;                        ////   
    }

    }
};

我能想到的唯一方法是使Struct全局化,但是根据我在这里Making Global Struct in C++ Program所读的内容,这似乎是不好的编码实践。

简而言之,我想知道-使用由某个外部事件触发的方法(DoOperate)修改类外部数据(Struct)的最佳实践是什么?

我已经为此苦苦挣扎了一段时间了,因此我们将不胜感激。

谢谢!

1 个答案:

答案 0 :(得分:0)

全局对象的问题之一是您可能会遇到初始化或销毁顺序的问题。因此,从理论上讲,DoOperate可能会在State state尚未初始化或已经被销毁时(在on应用程序退出时可能会被隐藏)时调用。

但是即使您的应用程序可能不是这种情况,您仍然希望通过设计使其安全。

对于您的MyCommandHandler,调用DoOperate并不重要,因此MyCommandHandler对象要么需要在整个生存期内拥有state,要么您可以如果仅在调用DoOperate时才需要将它作为参数传递给DoOperate

如果将其作为参数传递给DoOperate,则调用该运算符的对象应在整个生命周期内拥有状态对象,或者应将其作为调用DoOperate的函数的参数。 ...

如果您真的想使用全局状态对象,则可以这样:

std::shared_ptr<State> get_global_state() {
   static std::shared_ptr<State> state = std::make_shared<State>();

   return state;
}


class MyCommandHandler : public SimpleCommandHandler
{
public:
    MyCommandHandler() : state_(get_global_state()) {}

    static std::shared_ptr<ICommandHandler> Create()
    {
        return std::make_shared<MyCommandHandler>();
    }

    MyCommandHandler() : SimpleCommandHandler(CommandStatus::SUCCESS) {}

    void DoOperate(const ControlRelayOutputBlock& command, uint16_t index, OperateType opType) {
        // state_-> value0 = ...
    }

protected:
    std::shared_ptr<State> state_;
};

或者类似的代码,如果将其作为参数传递给DoOperate

struct HandlerCaller {
  void call_handlers() {
     for( auto &handler : handlers ) {
        handler->DoOperate(state_.get(), /*...*/ )
     }
  }

  std::shared_ptr<State> state_;
}


class MyCommandHandler : public SimpleCommandHandler
{
    void DoOperate(State * const state, const ControlRelayOutputBlock& command, uint16_t index, OperateType opType) {
        // state-> value0 = ...
    }
};

我个人不喜欢单例,但是重要的是这里的所有权。