Как я могу назвать метод данным только его имя?

Я пытаюсь иметь метод 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

Спасибо! :)

5
задан Rob Kennedy 23 December 2009 в 22:43
поделиться

9 ответов

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

Карта будет объявлена ​​как:

 std::map<std::string, void(Foo::*)()> function_map;
15
ответ дан 18 December 2019 в 05:33
поделиться

Как отмечали другие, C ++ не выполняет такого рода отражение из коробки (и есть вероятность, что это, вероятно, не то, чем вы хотите заниматься.)

Но я Я упомяну, что существуют некоторые препроцессоры, которые реализуют эту функциональность для подмножества типов и методов классов. Qt moc является примером этого, и это часть механизма сигналов / слотов. Обратите внимание на method () и methodCount () в QMetaObject ...

Qt делает это путем внедрения в процесс сборки инструмента, который создает таблицы и компилирует их вместе с остальной частью вашего кода. Это все, что вы могли бы написать от руки, а не языковая функция.

9
ответ дан 18 December 2019 в 05:33
поделиться

Уже упомянутое решение карты будет работать для фиксированных списков функций, но я не думаю, что в C ++ вообще есть способ такого самоанализа. То есть у вас не может быть функции void perform (string methodName) , которая говорит: «Есть ли у меня метод с именем methodName ? Если да, вызовите его».

6
ответ дан 18 December 2019 в 05:33
поделиться

Хотя предыдущие ответы относятся к вашему решению, ваше решение не выглядит правильным для вашей проблемы.

У меня есть два предложения: 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 

Установите базовый класс или интерфейс для функций, которые вы хотите использовать. Поместите их в контейнер и перебирайте по контейнеру.

3
ответ дан 18 December 2019 в 05:33
поделиться

Вы можете создать карту указателей на функции-члены, при этом ключ карты является именем функции. Однако с указателями на функции-члены немного сложно работать.

http://www.parashift.com/c++-faq-lite/pointers-to-members.html

Более простой способ - сделать кучу блоков if-then-else в вашем запустите функцию , чтобы вызвать соответствующую функцию.

2
ответ дан 18 December 2019 в 05:33
поделиться

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

Такие языки, как C # и Это встроено в Java, так что, возможно, стоит пересмотреть выбор языка, в зависимости от того, для чего вам это нужно.

1
ответ дан 18 December 2019 в 05:33
поделиться

Вы не можете сделать это без 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' );
}

это даст тот же результат, который вы хотели

-4
ответ дан 18 December 2019 в 05:33
поделиться

Для прямого C++ вышеприведенный ответ хорош. Однако, некоторые наборы инструментов (например, Qt) могут добавить к C++ интроспекцию. Возможно, это более тяжелое изменение и не то, что вы хотите для существующего проекта, но если вы начинаете проект, которому может понадобиться интроспекция, то вам стоит поискать наборы инструментов / обёртки, которые его добавляют.

1
ответ дан 18 December 2019 в 05:33
поделиться

Просто упомяну, что существуют некоторые библиотеки отражения, такие как CAMP: http://dev.tegesoft.com/projects/camp/apidoc/index.html

0
ответ дан 18 December 2019 в 05:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: