Полиморфизм в C при анализе пользовательского ввода

#c #polymorphism

#c #полиморфизм

Вопрос:

Я работаю над приложением, которое анализирует пользовательский ввод (команду) и пытается обработать команду. Существуют различные типы команд. Поэтому я создал один базовый класс, от которого будут унаследованы все команды. Сейчас я пытаюсь понять, как правильно обработать команду. Что я хотел бы сделать, так это создать экземпляр базового класса, а затем каким-то образом преобразовать его в правильного потомка. В идеале это должно быть сделано на уровне классов команд, например, Base, Der1, Der2, нет в основной функции, как в примере.

main.cpp

 #include "class1.hpp" int main(int argc, const char * argv[]) { Base com("some input"); com.process(); //based on the input I want to distinguish which of the derived classes should be used  }  

класс 1.ГЭС

 #include lt;iostreamgt;   class Base { std::string input; public:  Base(std::string input) {  this-gt;input = input; }  virtual void process(){} };  class Der1 { public:  Der1(std::string input);  void process() {  std::cout lt;lt; "Der1 process" lt;lt; std::endl;  } };  class Der2 { public:  Der2(std::string input);  void process() {  std::cout lt;lt; "Der2 process" lt;lt; std::endl;  } };  

Правильно ли это при анализе пользовательского ввода? Или, может быть, есть какой-то другой подход, который я мог бы попробовать? Я предпочитаю использовать полиморфизм как часть изучения c . Спасибо вам за любой ответ.

Комментарии:

1. Похоже, у вас должна быть функция, которая может выводить тип типа из входных данных и создавать класс на основе этого. Может быть, начать просто с switch ?

2. Вы, вероятно, ищете фабрику. Он принимает строковый ввод, анализирует его и создает объект связанного класса. Самое сложное-это разбор. В самой простой форме вам просто нужно сравнить входную строку с именами команд. Если у вас также есть переключатели, все становится сложнее. Base* make_command( const char* input ) {… .

3. У меня уже есть разбор, просто я не опубликовал его, чтобы упростить вопрос. Итак, я бы сделал эту функцию make_command, и на основе входных данных я бы создал объект типа Der1 или Der2 и вернул указатель на него?

4. @TobyV. Да, вы должны создать объект, производный от Base

5. Обратите внимание, что динамический полиморфизм работает только через указатель на базовый класс. Поэтому в любом месте, где вы хотите использовать динамический полиморфизм, вы управляете временем жизни объекта и виртуальным уничтожением или используете то, что управляет им (например, интеллектуальный указатель),

Ответ №1:

Правильно ли это при анализе пользовательского ввода?

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

Или, может быть, есть какой-то другой подход, который я мог бы попробовать?

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

 struct Der1 {  Der1(std::string_view); // TODO  auto process() { return "processed by Der1"sv; } };  struct Der2 {  Der2(std::string_view); // TODO  auto process() { return "processed by Der2"sv; } };  auto process(std::string_view input) {  switch (input.at(0)) { // I don't know how you actually want to choose DerN  case '1': return Der1{input}.process();  case '2': return Der2{input}.process();  default: throw std::runtime_error{"couldn't decide how to process"};  } }  int main() { std::cout lt;lt; process("1some input") lt;lt; 'n'; }  

Комментарии:

1. В C мы используем правильный инструмент для этой работы. Если подходящим инструментом для этой работы является динамический полиморфизм на основе наследования с виртуальной отправкой, мы используем его.

2. @n.1.8e9-где-моя-доля. Я имею в виду — он используется намного чаще, чем нужно. Когда вам действительно нужен динамический полиморфизм, вы, безусловно, идете на это.