我正在尝试使用 OOP 设计结构和原则为用户系统制作一个类似命令的界面。
所以我有一个抽象的 User 类和从它派生的不同类型的用户。
然后我有 CommandInterface 类 [获取输入字符串(用户输入拆分为 main 中的字符串?(stringstream)],它保存指向基类类型的 LoggedInUser 的指针(User *loggingInUser)并具有命令:
登录后,您还可以访问不同类型用户的命令(方法)。假设 User 有一个方法 print() 可以打印出所有用户数据。
User1:用户有方法a();
User2:用户有方法b();
现在如何在只有 User 类型(基类)的指针的情况下调用不同用户的不同方法?
代码(c++/伪):
#include <vector>
#include <string>
#include <unordered_map>
#include <memory>
class CommandInterface {
static unordered_map<std::string, std::unique_ptr<Command>>> interfaceCommands = {...};
std::shared_ptr<User> loggedUser = nullptr;
// Singleton
static CommandInterface* instance;
CommandInterface() = default;
std::unique_ptr<System> sys = System::getInstance(); // Instance to system which holds users (also singleton)
public:
// Singleton
CommandInterface(const CommandInterface& other) = delete;
CommandInterface(CommandInterface&& other) = default;
CommandInterface& operator=(const CommandInterface& other) = delete;
CommandInterface& operator=(CommandInterface&& other) = default;
~CommandInterface() = default;
static CommandInterface* getInstance();
// Commands
void signup(const std::string& name, uint8_t age, std::string& userType); // Adds users to System
void login(const std::string& name) {
if(loggedUser) {
throw std::exception();
}
else {
loggedUser = sys->getUser(name);
}
}
void exitCmd() {
if(loggedUser) {
loggedUser = nullptr;
}
else {
// Will be caught so that all the destructors are called
// Since std::exit(0) won't call the destructors
throw std::runtime_error("Exit.");
}
}
std::shared_ptr<User> &getLoggedUser(); // Getter, used by the commands
void executeCommand(const std::string& command, const std::vector<std::string>& args) {
if(!loggedUser) {
// Throw exception if command doesn't exist
interfaceCommands[command]->execute(args);
}
else {
// Throw exception if command doesn't exist (different users also hold static map of their commands to check)
loggedUser->getCommand(name)->execute(args); // Some pure virtual method
}
}
};
class Command {
public:
virtual ~Command() = default;
virtual void execute(const std::vector<std::string>& args) const = 0;
};
class PrintCMD : public Command {
public:
void execute(const std::vector<std::string>& args) const override {
CommandInterface::getInstance()->getLoggedUser()->print();
}
};
class ACMD : public Command {
public:
void execute(const std::vector<std::string>& args) const override {
CommandInterface::getInstance()->getLoggedUser()->a(); // Error Here
}
};
class BCMD : public Command {
public:
void execute(const std::vector<std::string>& args) const override {
CommandInterface::getInstance()->getLoggedUser()->b(); // Error Here
}
};
代码显示了示例实现,ACMD 和 BCMD 类中出现了 2 个错误,因为没有找到这样的方法。
那么问题是如何处理“隐藏”派生类方法的多态性?
您所需要的只是在基类中声明虚拟方法。例如:
class User:
{
virtual void execute(const std:vector<std::strings>& args) = 0;
}
现在,有了指向子级的 Base-Type 指针,您可以分配给子级重写的虚拟方法。
关于错误:
CommandInterface::getInstance()->getLoggedUser()->b();
尝试使用括号
(CommandInterface::getInstance()->getLoggedUser())->b();
还要确保这些 User 方法是公共的。