无法从映射中恢复指向成员函数的指针
Unable to recover a pointer to member function from a map
我的程序是评估和表征时间序列信息。 数据可能有大约 90 个不同的信号。 每个信号都有一个独特的公式和一组不同的参数和值。 这段代码和我的问题是为了从配置文件加载这些值。 编译器是VS 2010。
每个信号都由一个类表示,此处用类 TRI{} 表示,每个这样的类都派生自类 SIGNAL{}。 SIGNAL 包含一个静态映射(我的实际代码使用 unordered_map),用于保存信号名称和指向信号成员函数的指针,该函数将参数值分配给各自的变量。 我的问题是操纵这个成员函数。
显然,信号成员函数的地址,在这个代码 &TRI::load_cfg_vals 中,永远不会存储在映射中,sig_map。 所以从调试器看来。 当我尝试调用 TRI 信号的加载函数时,编译器说我正在尝试调用不是函数的东西。 请参阅我的一些失败尝试的代码。
如何让它与这些对象一起使用? 我真的不知道问题是什么,更糟糕的是,我不知道我对如何使用 STL 或C++有什么不了解。
(我准备放弃了。 我正在考虑另一种更像 C 的方法。 使用映射,将每个信号名称与一个唯一的整数相关联(已经在实际代码中 - 它们都表示为唯一的单个位)。 将 void 指针数组的每个元素加载到该元素数组中的信号的 load 函数的地址,该信号的整数值是该元素数组的偏移量。 我选择的第一种方法,下面的代码,似乎更容易维护,更高级一些。
在发布本文之前,我研究的许多问题和答案包括
成员函数指针和继承
C++ 字符串和成员函数指针的映射
C++指向成员函数的指针
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 foundn";
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;
}
保持简单,不要尝试将该指向成员的指针类型插入到map
只需尝试转换为PF
类型:
PF pf = &TRI::load_cfg_vals;
由于您链接到的一个问题的答案中解释的原因,这不会编译,就像这个简化的示例不会编译一样:
struct A {
virtual int f() = 0;
};
struct B : A {
int f() { return 0; }
};
int (A::*pf)() = &B::f;
因此,如果它不能编译,那么依赖于它但在更复杂的情况下,您的版本也不会编译。
为什么你不能这样做:
SIGNAL::sig_map.insert(std::make_pair ("tri",
&SIGNAL::load_cfg_vals));
&SIGNAL::load_cfg_vals
的类型与您尝试存储在map
中的类型相同,因此它可以工作。
这不会编译,因为dynamic_cast
的模板参数必须是类型而不是指向成员的指针:
SIGNAL::sig_map.insert( map<string, PF>::value_type("tri",
dynamic_cast< & SIGNAL::load_cfg_vals> (&TRI::load_cfg_vals) ));
dynamic_cast
用于将指针转换为多态类型,而不是指向成员类型的指针类型,这将进行编译,但最好避免强制转换:
SIGNAL::sig_map.insert( map<string, PF>::value_type("tri",
static_cast<PF> (&TRI::load_cfg_vals) ));
另外,为什么您的所有类型和类型定义都在ALL_CAPS?别喊了,ALL_CAPS是宏的,不要那样命名你的类型。
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 将公共但非静态的成员函数与ALGLIB集成
- 使用指向成员的指针将成员函数作为参数传递
- 将重载的成员函数传递给函数模板
- 我不小心调用了一个没有自己类对象的成员函数.但这是怎么回事呢
- 如何在C++中使用非静态成员函数作为回调函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 关联容器的下界复杂性:成员函数与非成员函数
- 在 C++ 中用派生类型重写成员函数
- 链表的泛型函数remove()与成员函数remove)
- 如何将lambda作为模板类的成员函数参数
- constexpr构造函数需要常量成员函数时出现问题
- 将自由函数绑定为类成员函数
- 区分非成员函数和头文件中的成员函数
- 如何从子成员函数修改父公共成员变量
- 保留对其他类的成员函数的引用
- 在运算符重载定义中使用成员函数(const错误)
- 内联如何影响模块接口中的成员函数
- 将成员函数指针作为参数传递给模板方法