gpt4 book ai didi

c++ - 如何使用 boost::signals 来实现观察者模式?

转载 作者:搜寻专家 更新时间:2023-10-31 00:43:32 24 4
gpt4 key购买 nike

我有一个由许多链接对象组成的应用程序,每个对象都有运行所需的参数。我正在使用 context 模式,以便每个对象根据构造时给出的上下文对象引用设置自己的参数。这在下面给出的简化代码示例中运行良好。

我要添加的下一个功能是观察者 模式,这样当上下文对象中的参数发生变化时,每个订阅者对象都会收到通知并相应地更新其参数。但是,我在计算将信号连接到槽时需要使用的语法时遇到了问题。

理想情况下,我想让订阅者对象在构造时用参数类注册自己,这样它们就可以在对象的生命周期内更新自己(即它们必须在销毁时注销自己,或者更好的是,使用某种RAII 技术在超出范围时注销自己)。下面是我希望尽可能简单的代码示例。

当前输出

Processing unit 0 param = 1

Processing unit 1 param = 2

Processing unit 0 param = 1

Processing unit 1 param = 2

目标是让它成为...

Processing unit 0 param = 1

Processing unit 1 param = 2

Processing unit 0 param = 11

Processing unit 1 param = 22

我目前正在使用的代码如下。如果您想尝试一下,它以目前的形式编译得很好。请提出我需要进行的更改,以便将我的信号连接到插槽。随时指出任何可能导致问题的设计问题。提前致谢。

//
// main.cpp
// context_observer
//

#include <iostream>
#include <sstream>
#include <map>

#include "boost/signals2.hpp"

/* This class holds the parameters and is the class that I want to set
* observable. It holds a std::map of the parameters and a simple accessor*/
class cParamsContext
{
typedef std::map<std::string, float> myMap_t;
typedef boost::signals2::signal<void (cParamsContext&)> signal_t;

myMap_t paramMap;


public:
signal_t sig;

cParamsContext()
{
paramMap["a0"] = 1.f;
paramMap["a1"] = 2.f;
}


float getParam( std::string key, float const & defaultVal )
{
myMap_t::iterator it = paramMap.find(key);
if ( it == paramMap.end() )
return defaultVal;
else
return it->second;
}

void changePars()
{
paramMap["a0"] = 11.f;
paramMap["a1"] = 22.f;
sig(*this);
}
};

/* This is an example of a processing class that I would like to have
* subscribe to the parameter class.*/
class cProcessingUnit
{
float parameter;
int id;

public:
cProcessingUnit(cParamsContext &contextObj, int id_) : parameter (80.f), id(id_)
{
updatePars(contextObj);
// Something like contextObj.sig.connect ... here
}

void updatePars(cParamsContext &contextObj)
{
std::stringstream idStream;
idStream << id;
std::string key = std::string( "a" + idStream.str() );

parameter = contextObj.getParam( key, parameter );
}

float getParam() {return parameter;}
};


/* This is a very simple main function used here for testing. It
* instantiates 2 processing objects. The parameters are then changed
* in the observable parameter object. The processing objects should
* then update themselves and so the last "cout" calls should reveal the
* new parameters. At least, this is what I would like to happen!*/
int main(int argc, char *argv[])
{
cParamsContext contextObj;

cProcessingUnit temp0(contextObj, 0);
cProcessingUnit temp1(contextObj, 1);

std::cout << "Processing unit " << 0 << " param = " << temp0.getParam() << std::endl;
std::cout << "Processing unit " << 1 << " param = " << temp1.getParam() << std::endl;

contextObj.changePars();

std::cout << "Processing unit " << 0 << " param = " << temp0.getParam() << std::endl;
std::cout << "Processing unit " << 1 << " param = " << temp1.getParam() << std::endl;
}

最佳答案

假设您希望在信号触发时调用 updatePars,您将连接到您评论过的地方:

// Something like contextObj.sig.connect ... here
contextObj.sig.connect(boost::bind(&cProcessingUnit::updatePars, this, _1));

您可能需要保留返回的连接,以便在您被销毁时可以断开连接。你的问题措辞不太好,所以很难说这是否是你真正需要的。

基本上,要连接到信号,您需要向其传递一个与信号签名匹配的“可调用实体”。这可以是一个 Binder (bind 和其他一些的结果)、一个自由函数、一个 lambda 表达式……一个自定义仿函数……等等……

我最新的博客条目可能会有一些帮助,但它相当快速和表面。

关于c++ - 如何使用 boost::signals 来实现观察者模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10418582/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com