boost — создает имя функции-члена и вызывает его во время выполнения в Stack Overflow

Может кто-нибудь дать мне представление об этой проблеме. Я искал в Интернете об этом, но не мог получить много информации, как я хотел.

Скажем, есть класс.

class Foo {
explicit Foo() {}

int getVar1();
int getVar2();

void setVar1(int v);
void setVar2(int v);

private:
int var1, var2;
};

Теперь, учитывая список токенов {«var1», «var2», … «varN»}, есть ли способ, которым я могу создать имя функции во время выполнения и вызвать эти функции-члены некоторого объекта типа Foo. как например

Foo obj;
string input = "Var1,Var2,Var3,...VarN";
vector<string> tokens = splitString(input);
for (vector<string>::const_iterator it = tokens.begin(); it != tokens.end(); ++it) {
string funName = "get" + *it;
// somehow call obj.getVar1()....obj.getVarN()
}

использование if else подходит для небольшого числа переменных, но не подходит для большого количества переменных. Использование связывания и функторов также не решает эту проблему. На одной веб-странице предлагалось сделать память исполняемой во время выполнения, а затем использовать reinterpret_cast, я не знаю, будет ли это работать.

ОБНОВИТЬ

Хорошо, из ответов и других поисков в Интернете я вижу, что в C ++ нет элегантного способа сделать это. На данный момент в C ++ нет отражения. Все взломы требуют разрешения времени компиляции указателей на функции-члены.
Может ли кто-нибудь дать мне идеи по проектированию альтернативных классов в этом сценарии, когда у вас много переменных, методов установки и методов получения … или есть ли методы получения и установки в C ++?

1

Решение

В качестве идеи рассмотрим следующий код

struct A
{
void f1() { std::cout << "A::f1()\n"; }
void f2() { std::cout << "A::f2()\n"; }
void f3() { std::cout << "A::f3()\n"; }
void f4() { std::cout << "A::f4()\n"; }
};

std::map<std::string, void( A::* )()> m = { { "f1", &A::f1 }, { "f2", &A::f2 }, { "f3", &A::f3 }, { "f4", &A::f4 } };

A a;

for ( auto p : m ) ( a.*p.second )();

Вы можете сделать карту как член данных вашего класса.

4

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

Вы не можете «добавлять» участников во время выполнения. C ++ строго типизирован во время компиляции.

Вы можете получить желаемое поведение, имея map<string, func_type> и использовать его, чтобы преобразовать вашу строку в реальную функцию. Вы можете создать его, используя макросы, чтобы убедиться, что имена строк соответствуют именам функций.

#DEFINE ADD_METHOD(map_var, func) map_var["func"] = &func
2

Простое / не идеальное решение может заключаться в использовании промежуточных методов, проверяющих параметр и вызывающих метод getVar * соответственно.

Пример, подобный этому, может быть:

class Foo
{
public:
explicit Foo() {}

int getVar1() { return 1; }
int getVar2() { return 2; }

void setVar1(int v) { var1 = v; }
void setVar2(int v) { var2 = v; }

int callGetVar(const std::string &var)
{
if (var == "Var1") return getVar1();
if (var == "Var2") return getVar2();
else { return -1; }
}

private:
int var1, var2;
};

int main()
{
Foo obj;
std::string input = "Var1,Var2,Var3,...VarN";
std::vector<std::string> tokens = { "Var1", "Var2", "Var2", "Var1", "Var1", "Var2", "Var2", "Var1"};
auto tokensIT = tokens.begin();
for (; tokensIT != tokens.end(); ++tokensIT)
{
// somehow call obj.getVar1()....obj.getVarN()
std::cout << obj.callGetVar(*tokensIT);
}

return 0;
}
0

почему бы не посмотреть на это референтным способом:
Для каждой переменной присваивают порядковый номер, начиная с 0, 1, 2 ….
Вы сохраняете эти значения на карте (ключ — это имя переменной, значение — это назначенное значение).
Все значения этих переменных вы храните в массиве, так что значение первой переменной в ячейке 0, следующей — в ячейке 1 и т. Д.

поэтому, когда вы хотите получить / установить значение, все, что вам нужно сделать, это найти его индекс на карте и получить доступ к соответствующей ячейке в векторе.

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