我正在编写一个小型数据库,似乎遇到了问题。我有 3 Statement
类型(每个对应 CREATE
, INSERT
和 SELECT
。这些类型的定义是:
class Statement { }; // Base class, contains common stuff like the table name
class CreateStatement : public Statement {
/* Contains information regarding the CREATE statement after parsing (name and datatype of
each column) */
}
class InsertStatement : public Statement {
/* Contains information regarding the INSERT statement (list of values to enter inside the DB) */
}
class SelectStatement : public Statement {
/* Contains information regarding the SELECT statement ( list of attributes to select from the DB) */
}
我的解析器具有适当解析这 3 种类型的输入语句的函数,但我从这些函数中的每一个返回基类。一个例子是:Statement parse_create(const std::string& stmt) {
CreateStatement response;
// Parse stmt
return response;
}
我这样做的理由是避免在我的主 REPL 循环中出现 if/else 情况(而不是检查输入是否属于 create 类型,然后有条件地返回 CreateStatement
或其他派生类,只需调用一次 parse
就会返回一个 Statement
对象)。我遇到的问题是执行返回的 Statement
.我有 3 个不同的函数来执行这些命令( execute_create
、 execute_insert
和 execute_select
),它们分别将派生类作为参数( CreateStatement
、 InsertStatement
和 SelectStatement
)。这样执行函数就可以在解析时利用存储在派生类对象中的信息。我可以使用某种模板逻辑来调用适当的执行函数,还是在解析后返回基类后丢失派生类的信息?我尝试做一些类似的事情:
Statement parsed_stmt = parse(input); // input is the string the user entered
if (std::is_same_v<decltype(input), CreateStatement>) {
execute_create(parsed_stmt);
}
但这显然行不通,因为类型是明确的 Statement
.我也将不胜感激有关设计的任何反馈。谢谢!
最佳答案
我这样做的方式是这样的:
class Statement {
...
virtual void parse(const std::string &stmt) = 0; // A string view will work here too.
virtual bool execute() = 0;
...
};
class Create : public Statement {
...
virtual void parse(const std::string &stmt); // Implement
virtual bool execute(); // Implement
...
};
... // more statements
然后在派生类中适本地实现这些。您可以解析非虚拟并调用虚拟 create
方法,但这对我来说似乎是多余的。注释创建不返回任何内容 - 它只是更改对象的状态(存储语句或其他内容)。同样,
execute
存储在派生类中,因此它知道如何执行自身 - 即使您引用了 Statement
对象,正确的派生方法将被调用而无需额外的努力。我假设返回一个 bool 值表示成功。这意味着您需要使用对语句的引用(或指针)。这是多态性继承的主要优势——能够以相同的方式对不同的派生对象进行操作,而不必担心它们究竟是什么。
关于c++ - 使用模板逻辑在运行时从基类转换为派生类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64003591/