Я пытаюсь иметь метод void run( string method )
который выполнил бы метод в том классе. Например:
class Foo {
public:
void run( string method ) {
// this method calls method *method* from this class
}
void bar() {
printf( "Function bar\n" );
}
void foo2() {
printf( "Function foo2\n" );
}
}
Foo foo;
int main( void ) {
foo.run( "bar" );
foo.run( "foo2" );
}
это распечатало бы:
Function bar
Function foo2
Спасибо! :)
Вы можете создать std :: map
, который сопоставляет строки указателям на функции-члены, если все функции, которые вы хотите вызвать, имеют одинаковую сигнатуру.
Карта будет объявлена как:
std::map<std::string, void(Foo::*)()> function_map;
Как отмечали другие, C ++ не выполняет такого рода отражение из коробки (и есть вероятность, что это, вероятно, не то, чем вы хотите заниматься.)
Но я Я упомяну, что существуют некоторые препроцессоры, которые реализуют эту функциональность для подмножества типов и методов классов. Qt moc является примером этого, и это часть механизма сигналов / слотов. Обратите внимание на method ()
и methodCount ()
в QMetaObject ...
Qt делает это путем внедрения в процесс сборки инструмента, который создает таблицы и компилирует их вместе с остальной частью вашего кода. Это все, что вы могли бы написать от руки, а не языковая функция.
Уже упомянутое решение карты будет работать для фиксированных списков функций, но я не думаю, что в C ++ вообще есть способ такого самоанализа. То есть у вас не может быть функции void perform (string methodName)
, которая говорит: «Есть ли у меня метод с именем methodName
? Если да, вызовите его».
Хотя предыдущие ответы относятся к вашему решению, ваше решение не выглядит правильным для вашей проблемы.
У меня есть два предложения: 1) создать лучший абстрактный базовый класс или 2) использовать базовый класс для функторов (функциональных объектов) . Давайте рассмотрим их более подробно ...
Учитывая проект моделирования набора команд процессора, мы можем моделировать выполнение с помощью:
struct Instruction_Interface
{
virtual void execute(void) = 0;
};
typedef std::vector<Instruction_Interface *> Instruction_Container;
//...
Instruction_Container::iterator iter;
Instruction_Container program_instructions;
//...
for (iter = program_instructions.begin();
iter != program_instructions.end();
++iter)
{
(*iter)->execute(); // Execute the instruction;
}
Это позволяет вызывать метод execute
каждой инструкции, независимо от того, вид инструкции. В интерфейс можно добавить больше методов; в этом примере можно добавить «toString», который преобразует инструкцию в текст.
Idea 2: Functors
Установите базовый класс или интерфейс для функций, которые вы хотите использовать. Поместите их в контейнер и перебирайте по контейнеру.
Вы можете создать карту указателей на функции-члены, при этом ключ карты является именем функции. Однако с указателями на функции-члены немного сложно работать.
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
Более простой способ - сделать кучу блоков if-then-else в вашем запустите функцию
, чтобы вызвать соответствующую функцию.
Как было сказано на других плакатах, вам нужно сделать это вручную на C ++, поскольку язык не имеет встроенного Reflection .
Такие языки, как C # и Это встроено в Java, так что, возможно, стоит пересмотреть выбор языка, в зависимости от того, для чего вам это нужно.
Вы не можете сделать это без RTTI или какой-либо карты. Или подобное решение:
class Foo { public: void run( string method ) { bar(method); foo2(method); // ... more methods here } void bar(string method) { if (method != "bar") return; printf( "Function bar\n" ); } void foo2(string method) { if (method != "foo2") return; printf( "Function foo2\n" ); } } Foo foo; int main( void ) { foo.run( 'bar' ); foo.run( 'foo2' ); }
это даст тот же результат, который вы хотели
Для прямого C++ вышеприведенный ответ хорош. Однако, некоторые наборы инструментов (например, Qt) могут добавить к C++ интроспекцию. Возможно, это более тяжелое изменение и не то, что вы хотите для существующего проекта, но если вы начинаете проект, которому может понадобиться интроспекция, то вам стоит поискать наборы инструментов / обёртки, которые его добавляют.
Просто упомяну, что существуют некоторые библиотеки отражения, такие как CAMP: http://dev.tegesoft.com/projects/camp/apidoc/index.html