#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-где-моя-доля. Я имею в виду — он используется намного чаще, чем нужно. Когда вам действительно нужен динамический полиморфизм, вы, безусловно, идете на это.