私は多くのリンクされたオブジェクトで構成されるアプリケーションを持っています。それぞれのオブジェクトには、機能するために必要なパラメーターがあります。私はコンテキストパターンを使用しているので、各オブジェクトは、構築時に与えられるコンテキストオブジェクト参照に従って独自のパラメーターを設定します。これは、以下に示す簡略化されたコード例でうまく機能します。
私が追加しようとしている次の機能はオブザーバーパターンです。これにより、コンテキストオブジェクトのパラメーターが変更されると、各サブスクライバーオブジェクトに通知され、それに応じてパラメーターが更新されます。ただし、信号をスロットに接続するために使用する必要のある構文を理解するのに問題があります。
理想的には、サブスクライバーオブジェクトを構築時にパラメータークラスに登録して、オブジェクトの存続期間中更新できるようにします(つまり、破棄時に登録を解除する必要があります。さらに、何らかのRAII手法を使用する必要があります。範囲外になった場合は登録を解除します)。以下は、私が可能な限り単純に要約したコード例です。
出力は現在です
処理装置0param= 1
処理装置1param= 2
処理装置0param= 1
処理装置1param= 2
目標はそれを実現することです...
処理装置0param= 1
処理装置1param= 2
処理装置0param= 11
処理装置1パラメーター=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;
}