我有一個應用程序由許多鏈接的對象組成,每個鏈接對象都有它們需要的參數才能起作用。我正在使用上下文模式,以便每個對象根據構建時給出的上下文對象參考設置自己的參數。這在下面給出的簡化代碼示例中運行良好。如何使用boost :: signals來實現觀察者模式?
我試圖添加的下一個功能是觀察者模式,以便當上下文對象中的參數發生更改時,會通知每個訂閱服務器對象並相應地更新其參數。但是,我無法解決爲了將信號連接到插槽而需要使用的語法。
理想情況下,我希望訂閱者對象在構造時向參數類註冊自己,以便他們可以在對象的生命週期內更新自己(即他們必須在銷燬時註銷自己,或者更好地使用一些如果RAII技術超出了範圍,那麼可以註銷自己的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;
}
感謝您的回答!對這個問題的措辭感到抱歉。當我對boost :: signals非常無知時,很難很好地表達它。我會檢查你的博客。您發佈的代碼給出了以下編譯錯誤: – learnvst
main.cpp:在構造函數'cProcessingUnit :: cProcessingUnit(cParamsContext&,int)'中: – learnvst
main.cpp:60:錯誤:沒有用於調用'bind(<未解決的重載函數類型>,cProcessingUnit&,升壓:: ARG <1>&)」 /編程/軟件開發工具包/升壓/升壓/結合/綁定。hpp:1480:注意:候選是:boost :: _ bi :: bind_t :: type> boost :: bind(F,A1,A2 )[with F = void(cProcessingUnit :: *)(cParamsContext&),A1 = cProcessingUnit,A2 = boost :: arg ] –
learnvst