私のプログラムは、時系列情報を評価して特徴付けることです。データが持つ可能性がある約 90 の異なる信号があります。各信号には、独自の式と、パラメーターと値の個別のセットがあります。このコードとそれに関する私の問題は、構成ファイルからこれらの値をロードするためのものです。コンパイラはVS2010です。
各シグナルはクラスによって表され、ここではクラス TRI{} で示され、そのような各クラスはクラス SIGNAL{} から派生します。SIGNAL には静的マップが含まれています (私の実際のコードでは unordered_map を使用しています)。これは、シグナル名とパラメーター値をそれぞれの変数に割り当てるシグナルのメンバー関数へのポインターのペアを保持するためのものです。私の問題は、このメンバー関数を操作することです。
どうやら、このコード &TRI::load_cfg_vals 内のシグナルのメンバー関数のアドレスは、マップ sig_map に格納されることはありません。デバッガーからのようです。TRI シグナルのロード関数を呼び出そうとすると、関数ではないものを呼び出そうとしているとコンパイラが言います。私の失敗した試みのいくつかについては、コードを参照してください。
これをこれらのオブジェクトで動作させるにはどうすればよいですか? 何が問題なのか本当にわかりません。さらに悪いことに、STL や C++ の使用方法について何が理解できていないのかもわかりません。
(私はあきらめる準備ができています。代替の、より C に似たアプローチを検討しています。マップを使用して、各信号名を一意の整数に関連付けます (既に実際のコードで - それらはすべて一意の単一として表されます)。整数値がその要素の配列へのオフセットであるシグナルのロード関数のアドレスを使用して、void ポインターの配列の各要素をロードします. 私が選択した最初の方法である以下のコードは、維持しやすいように見えました.もう少しレベルが高い。)
これを投稿する前に私が研究した多くの質問と回答の中には、
C++ const 関数からのマップを使用してメンバーへのポインターを呼び出す
ティア
#include <iostream>
#include <map>
#include <string>
using namespace std;
typedef std::map< string, void *> ARG_MAP;
typedef ARG_MAP::iterator ARG_ITR;
typedef std::pair < ARG_ITR, bool> ARG_PAIR;
// forward decl
class SIGNAL;
typedef int (SIGNAL::*PF)(void);
typedef std::map< string, PF> SIG_MAP;
typedef SIG_MAP::iterator SIG_MAP_ITR;
typedef std::pair < SIG_MAP_ITR, bool> SIG_MAP_PAIR;
class SIGNAL
{
public:
ARG_MAP arg_map;
ARG_ITR ai;
ARG_PAIR ap;
static SIG_MAP sig_map;
SIGNAL() {};
~SIGNAL(){};
virtual int calc() = 0;
virtual int load_cfg_vals() = 0;
};
// tried globals versus members, no difference
SIG_MAP SIGNAL::sig_map;
SIG_MAP_ITR smi;
SIG_MAP_PAIR smp;
class TRI: public SIGNAL
{
public:
float f;
int calc(){return 1;}
int load_cfg_vals()
{
// the f arg
ai = arg_map.find("f_descriptive_name");
*(float *) ai->second = (float)12.005;
return 1;
};
TRI()
{
// associates the TRI class function 'load_cfg_vals()' with the
// signal name 'tri'
SIGNAL::sig_map.insert(std::make_pair ("tri",
(PF) &TRI::load_cfg_vals));
// this apparently doesn't load the address of the function, see below
//sig_map.insert(std::make_pair ("tri",&TRI::load_cfg_vals));
// fails with error C2440: 'initializing' : cannot convert from
// from 'int (__thiscall TRI::* )(void)' to 'PF '
//SIGNAL::sig_map.insert( map<string, PF>::value_type("tri",
// dynamic_cast< & SIGNAL::load_cfg_vals> (&TRI::load_cfg_vals) ));
// C2059: syntax error : '&'
// so, maybe this is right but for my lack of understanding of what
// types are involved/required here
// contains the list of descriptive names of the signal's parameters
// and the addresses of the variables that hold the parameters'values
arg_map.insert(std::make_pair ("f_descriptive_name", (void*) &f));
};
~TRI(){};
};
int main(void)
{
TRI tri;
PF pf;
char * input_str = "tri"; // this and the names of the many other
// signals would be read from the cfg file
// while there are still more signal names to read in
// while( fscanf(...input_str...) { removed
if( (smi = tri.sig_map.find (input_str)) == tri.sig_map.end())
cout << "'" << input_str << "' not found\n";
else
{
// smi->second is supposed to contain the function of the
// signal class that is to properly interpret and handle
// the list of values stored in the cfg file
//(smi->second)();
// error C2064: term does not evaluate to a function taking
// 0 arguments
string s = smi->first; // OK
pf = (PF)smi->second;
// Doesn't contain the address of the function that was
// loaded, above, in TRI(). The debugger identifies
// it as TRI::`vcall'{4}', I don't know what that is.
// Debugger emits the entire type of the operator and
// its return value, but I can't get it to format for
// proper display here. If someone wants to see it,
// I'll supply it unformatted.
//int z = (*pf)();
// error C2064: term does not evaluate to a function taking 0
// arguments
// the following don't help the value in pf. same error C2064 or
// complaints about improper use of the casts
//pf = reinterpret_cast <int (__thiscall *)(void)>(smi->second);
//pf = static_cast <int (__thiscall *)(void)>(smi->second);
}
// } // end while removed
return 1;
}