преобразовать строку / символ в член / метод класса в переполнении стека

Есть ли способ преобразовать строку или символы в функции класса / члена-члена для динамического доступа к ним?

например этот конкретный код,

 #include <iostream>
#include <map>

using namespace std;

class agnt {
public:
int x, y;
agnt(int a=0, int b=0) : x(a), y(b) {}
};int main() {
map<int,agnt> agntID;
agnt temp;
temp.x=1;
temp.y=5;

agntID[1]=temp;

for(char tmp='x'; tmp<'z'; tmp++) {
cout<<agntID[1].tmp<<'\n';     //Here I get the following error: tmp is
}                              //not a member of class agnt
}

Есть ли способ преобразовать символ ‘tmp’ так, чтобы он был идентифицирован как член класса? Любые советы или решения будут оценены.

3

Решение

Вы не можете сделать это в C ++, потому что это статически типизированный язык. Один из способов получить такое поведение — предоставить доступ к оболочкам:

template <char c>
struct getter {
};template <>
struct getter<'x'> {
static int get(const agnt &theAgnt) {
return theAgnt.x;
}
};template <>
struct getter<'y'> {
static int get(const agnt &theAgnt) {
return theAgnt.y;
}
};

template <char c>
int get(const agnt &theAgnt) {
return getter<c>::get(theAgnt);
}

И звоните как:

agnt temp;
//... set members
std::cout << get<'x'>(temp) << std::endl;

Тем не менее for Цикл не будет работать так, как вы ожидаете, потому что параметры шаблона должны быть определены во время компиляции. Кроме того, вы не можете просто запросить любую старую вещь, если вы не определите get функционировать в неспециализированных getter который возвращает какой-то NULL-индикатор, например INT_MIN,

тем не мение, это все на самом деле взломать, чтобы получить что-то неясно похож на динамический язык. Но это на самом деле ничем не отличается от просто ссылки temp.x, Вместо этого вы должны стараться придерживаться соглашений C ++ и наслаждаться статической типизацией!

1

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

C ++ не имеет никакого интроспекция так что нет, это невозможно.

Тем не менее, вы можете взломать его, имея другой std::map который содержит имена в качестве ключей, а значение является ссылкой на переменную:

agnt temp;

std::unordered_map<char, int&> variable_map = {
{ 'x', temp.x },
{ 'y', temp.y }
};

variable_map['x'] = 123;
std::cout << variable_map['y'] << '\n';

Это вообще не стоит того, хотя, поскольку это больше работает. Особенно, если вы хотите сделать это для нескольких переменных (так как каждая структурная переменная требует своего отображения).

2

нет

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

Разумная альтернатива ручному кодированию может в некоторых случаях использовать внешний файл схемы для описания ваших классов C ++, а затем автоматически генерировать классы и код самоанализа и отражения. Вы не можете сделать это, используя шаблоны, потому что даже возможности метапрограммирования C ++ полностью отсутствуют в этой области.

Генерация кода путем непосредственного разбора .h в общем случае это может быть намного сложнее из-за того, насколько сложен синтаксис C ++ (даже производителям компиляторов потребовалось довольно много лет, чтобы в достаточной степени договориться о том, что является допустимым кодом C ++, а что нет).

Вы можете использовать шаблоны для упрощения публикации, но все же делать это вручную:

template<typename T, typename C>
std::map<std::string, T C::*>& attribute_map() {
static std::map<std::string, T C::*> m;
return m;
}

template<typename C>
struct Published {
template<typename T>
T& attribute(const std::string& name) {
std::map<std::string, T C::*>& m = attribute_map<T, C>();
typename std::map<std::string, T C::*>::const_iterator i=m.find(name);
if (i == m.end()) {
throw std::runtime_error("Attribute not present");
} else {
return static_cast<C *>(this)->*i->second;
}
}
};

Для каждого атрибута вам нужно будет явно «опубликовать» его

template<typename T, typename C>
void publish(const std::string& name, T C::*mp) {
attribute_map<T, C>()[name] = mp;
}

С учетом приведенного выше стандартного кода вы можете создать класс и опубликовать некоторые его члены, выведя из Published<Class>:

struct MyClass : Published<MyClass> {
int a;
double b;
std::string c;

MyClass(int a, double b, const std::string& c)
: a(a), b(b), c(c)
{
}
};

Тогда вам нужно будет позвонить publish Функция только один раз в начале программы, чтобы иметь возможность динамического доступа к атрибутам:

int main(int argc, const char *argv[]) {
publish("a", &MyClass::a);
publish("b", &MyClass::b);
publish("c", &MyClass::c);

MyClass m1(3, 4.5, "This is a test");
MyClass m2(6, 7.8, "This is another test");

std::cout << m1.attribute<int>("a") << "\n";
std::cout << m2.attribute<std::string>("c") << "\n";
return 0;
}
1

Хотя все, кто ответил «НЕТ», правы … Это не говорит о всей истории.
В языке нет ничего, что позволяло бы вам делать это, однако это не означает, что среда этого не позволяет.

Например, на vxworks вы можете позвонить symFindByName() для поиска функции, переменной или любого другого символа, и затем вы можете вызвать функцию через указатель, который она предоставляет. Но это зависит от API ОС и, вероятно, является побочным эффектом работы компоновщика vxworks.

Другие ОС могут иметь аналогичные функции.

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