main()がオブジェクトMyAppをインスタンス化し、そのオブジェクトをReadConfig関数に渡すC++アプリケーションがあります。関数ポインタを使用して異なるシグネチャでC++関数を呼び出す方法
ReadConfigは、テキストベースのファイルを開き、解析し、適切なMyAppメソッドを呼び出して設定します。
class MyApp
{
private:
public:
void SetRate(uint16_t);
void EnableLogging(bool);
void SetAddress(uint32_t);
};
私は、新しい公開メソッドがMyAppに追加されると、テーブルを更新するなどの簡単な操作が可能なように、ReadConfigのメンテナンスを容易にしようとしています。私は以下の解決策を思いついたが、私はそれが好きではない。私が正しい場所に0を入れていることを確認する必要があるため、維持するのは難しいです。
以下は、私が解決した例です。これをより良くするためのアドバイスは高く評価されます。私が組み込みで作業するので、使用するC++コンパイラはC++をサポートしていません14 &追加機能はありません。そして、私はこれを自分でやることの仕組みを理解するために、STLライブラリの使用を避けたいと思います。ここで
は、私が持っているものです:私は、設定ファイルを読み込み、それを解析として
enum ARGTYPE {TBOOL, TUINT16, TUINT32};
template<typename TOBJ, typename TARG>
struct TSetting
{
void (TOBJ::*FSet)(TARG);
};
template<typename obj>
struct SETTINGFN
{
const char *setting_name;
ARGTYPE Targ;
TSetting<obj,bool> HBool;
TSetting<obj,uint16_t> HUint16;
TSetting<obj,uint32_t> HUint32;
};
SETTINGFN<MyApp> MyAppSettings[] =
{
"logging" ,TBOOL, &MyApp::EnableLogging, 0,0,0
,"maxrate" ,TUINT16, 0,0,0,&MyApp::SetRate
,"address" ,TUINT32, 0, &MyApp::SetAddress, 0,0
};
unsigned int MyAppSettings_Count = sizeof(MyAppSettings)/sizeof(SETTINGFN<MyApp>);
はその後、私は、関数ポインタを通じて、実際のMyApp関数を呼び出す処理するための関数を呼び出します。その機能は次のとおりです。
bool AppSetting(MyApp &E, TObjnode &node)
{
bool rval = false;
for(unsigned int i=0; i<MyAppSettings_Count && !rval; i++)
{
if(node.GetName() == MyAppSettings[i].setting_name)
{
rval = true;
switch(MyAppSettings[i].Targ)
{
case TBOOL:
(E.*MyAppSettings[i].HBool.FSet)(node.GetValue().AsBool());
break;
case TUINT16:
(E.*MyAppSettings[i].HUint16.FSet)(node.GetValue().Value());
break;
case TUINT32:
(E.*MyAppSettings[i].HUint32.FSet)(node.GetValue().Value());
break;
}
}
}
return(rval);
}
?すべてのセッターは同じタイプにすることができます。文字列を受け取り、解析関数と型保証セッターの両方を呼び出すトランポリンはもっと良いかもしれません。 –
...新しいプロパティ/セッターが追加されるたびに、コンフィギュレーションディスパッチルーチンに関数呼び出しを追加する必要を避けるために、新しいプロパティ/セッターが追加されるたびにプロプライエタリデータ構造を更新したいですか?それぞれ自分自身に... –
私はこれらのことを考えましたが、現在の関数のシグネチャを変更したり新しいものを追加することを避けることを望んでいました – Eric