Как реализовать наследование статического поля/метода, если это возможно? Пишу эмулятор терминала Linux (типа Bash) для курсовой. Получается я создал абстрактный базовый класс Command.class Command { public: Command(const std::string&); std::vector getArguments(); std::vector getOptions(); virtual void execute(Directory& currentDirectory) = 0; virtual std::string getCommandName() = 0; protected: std::vector arguments_; std::vector options_; void parseStr(std::string); }; От него наследуются уже рабочие комманды, которые реализуют метод execute и как-то должны реализовать своё название (пример: cp, cd, ls, pwd). Проблема в том, что не знаю как грамотно реализовать то, что у каждой комманды должно быть своё название. Оно естественно должно быть статическим. Думаю, что в C#/Java это реализуется через интерфейсы, но ведь в С++ их нету. Возможно вы уже заметили, я решил реализовать это через метод getCommandName, которые производные классы обязаны реализовать. Но в таком случае для того, чтобы получить название комманды нужно обязательно создать его объект, ибо виртуальный метод не может быть статическим. Мне это нужно для того, чтобы реализовать такой алгоритм: Считываю введённую пользователем строку. Делаю split по пробелам (учитываю скобки и т.д.) и за счёт этого получаю название комманды. Создаю указатель на Command (базовый абстрактный класс). Закидываю названия комманд в комманд в некий контейнер (стек, вектор пофиг, но реализую через вектор). Здесь и возникла эта проблема, ибо не охота создавать экземпляр каждого класса. Сравниваю полученное название комманды с названиями в классах. Создаю объект соответствующего класса и записываю его адресс в указатель на Command. Получается такая красивая запись, ради которой столько мучаюсь command->execute(/* Current directory.*/) Что посоветуете?
Ваш подход с использованием метода getCommandName для получения названия команды вполне адекватен для этой задачи. Однако, чтобы избежать создания экземпляров каждого класса команды для получения их названия, вы можете использовать статические поля или методы их классов-наследников.
Вы можете добавить статическое поле в каждый класс-наследник, в котором будет храниться имя соответствующей команды, и реализовать статический метод в базовом классе, который будет возвращать это статическое поле. Например:
class Command { public: // остальные методы static std::string getCommandName() { return "DefaultCommand"; } }; class CopyCommand : public Command { public: void execute(Directory& currentDirectory) override { // реализация команды cp } static std::string getCommandName() { return "cp"; } }; // другие классы с командами
Затем вы можете обращаться к статическому методу getCommandName из класса Command, чтобы получить название соответствующей команды.
std::string commandName = "cp"; // полученное название команды Command* command = nullptr; if (commandName == CopyCommand::getCommandName()) { command = new CopyCommand(); } else { // обработка других команд } command->execute(/* Current directory.*/);
Таким образом, вы сможете получить название команды без создания экземпляров каждого класса команды.
Ваш подход с использованием метода getCommandName для получения названия команды вполне адекватен для этой задачи. Однако, чтобы избежать создания экземпляров каждого класса команды для получения их названия, вы можете использовать статические поля или методы их классов-наследников.
Вы можете добавить статическое поле в каждый класс-наследник, в котором будет храниться имя соответствующей команды, и реализовать статический метод в базовом классе, который будет возвращать это статическое поле. Например:
class Command{
public:
// остальные методы
static std::string getCommandName() { return "DefaultCommand"; }
};
class CopyCommand : public Command
{
public:
void execute(Directory& currentDirectory) override
{
// реализация команды cp
}
static std::string getCommandName() { return "cp"; }
};
// другие классы с командами
Затем вы можете обращаться к статическому методу getCommandName из класса Command, чтобы получить название соответствующей команды.
std::string commandName = "cp"; // полученное название командыCommand* command = nullptr;
if (commandName == CopyCommand::getCommandName())
{
command = new CopyCommand();
}
else
{
// обработка других команд
}
command->execute(/* Current directory.*/);
Таким образом, вы сможете получить название команды без создания экземпляров каждого класса команды.