Невозможно восстановить указатель на функцию-член с карты

Моя программа заключается в оценке и характеристике информации временных рядов. Есть около 90 различных сигналов, которые могут иметь данные. Каждый сигнал имеет уникальную формулу и отдельный набор параметров и значений. Этот код и мои проблемы с ним для загрузки этих значений из файла конфигурации. Компилятор VS 2010.

Каждый сигнал представлен классом, проиллюстрированным здесь классом TRI {}, и каждый такой класс является производным от класса SIGNAL {}. SIGNAL содержит статическую карту (мой настоящий код использует unordered_map), которая должна содержать пары имен сигналов и указателей для функции-члена сигнала, которая присваивает значения параметров их соответствующим переменным. Моя проблема с манипулированием этой функцией-членом.

Видимо, адрес функции-члена сигнала, в этом коде &TRI :: load_cfg_vals, никогда не сохраняется на карте, sig_map. Так кажется из отладчика. Когда я пытаюсь вызвать функцию загрузки сигнала TRI, компилятор говорит, что я пытаюсь вызвать что-то, что не является функцией. Пожалуйста, посмотрите код для некоторых из моих неудачных попыток.

Как я могу заставить это работать с этими объектами? Я действительно не знаю, в чем проблема, и что еще хуже, я не знаю, что я не понимаю о том, как использовать STL или C ++.

(Я готов сдаться. Я рассматриваю альтернативный, более C-подобный подход. Используя карту, свяжите каждое имя сигнала с уникальным целым числом (уже в фактическом коде — все они представлены как уникальное единственное биты). Загрузите каждый элемент массива пустых указателей с адресом функции загрузки сигнала, целочисленное значение которого является смещением, в массив этого элемента. Первый способ, который я выбрал, код, приведенный ниже, казался более простым в поддержке, немного более высокого уровня.)

Среди множества вопросов и ответов, которые я изучал до публикации, были

указатели на функции-члены и наследование

C ++ Карта строки и указатель на функцию-член

C ++ указатели на функции-члены

C ++ Вызов указателя на член с картой из константной функции

ТИА

#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;
}

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 для макросов, не называйте ваши типы так.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]