Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用模板逻辑在运行时从基类转换为派生类_C++_Oop_C++14_C++17 - Fatal编程技术网

C++ 使用模板逻辑在运行时从基类转换为派生类

C++ 使用模板逻辑在运行时从基类转换为派生类,c++,oop,c++14,c++17,C++,Oop,C++14,C++17,我正在写一个小型数据库,似乎遇到了一个问题。我有3种语句类型(每种类型对应于创建、插入和选择。这些类型的定义是: class Statement { }; // Base class, contains common stuff like the table name class CreateStatement : public Statement { /* Contains information regarding the CREATE statement after parsing

我正在写一个小型数据库,似乎遇到了一个问题。我有3种
语句
类型(每种类型对应于
创建
插入
选择
。这些类型的定义是:

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
一次,就会返回
语句
对象)。我遇到的问题是对返回的
语句执行。我有3个不同的函数来执行这些命令(
execute\u create
execute\u insert
execute\u 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 parsed_stmt=parse(input);//input是用户输入的字符串
如果(标准::是否相同){
执行创建(已解析的stmt);
}
但这显然不起作用,因为类型是显式的
语句


我也非常感谢对设计的任何反馈。谢谢!

我会这样做:

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
存储在派生类中,因此它知道如何执行自己-即使有对
语句
对象的引用,也会调用正确的派生方法,而无需额外努力。我假设返回一个布尔值以指示成功

这意味着您需要使用对语句的引用(或指针)。这是多态性继承的主要优点—能够以相同的方式对不同的派生对象进行操作,而不必担心它们到底是什么。

动态分派:

struct Base {
  abstract virtual void method() = 0;
  virtual ~Base() = default;
};

struct Derived: Base {
  void method() override {}
};
静态调度(CRTP),通常是超压:

template <class D> struct Base {
  void method() {
    static_cast<D*>(this)->method();
  }
};

struct Derived: Base<Derived> {
  void method() { ... }
};
模板结构库{
void方法(){
静态_cast(this)->method();
}
};
派生结构:基{
void方法(){…}
};

当您按值返回对象时。多态性仅适用于引用或指针。这当然假设您的类层次结构从一开始就是多态的。如果不是,则指向基类的指针或引用如果没有大量的上下转换将无法工作。这类工具的“转到”工具是一个虚拟函数,而不是模板。你尝试过了吗?你不能通过对基本类型的值来返回,它会对你的对象进行切片,并删除任何派生的功能。欢迎来到C++,在这里,由于设计不好,功能相互冲突。非常感谢,这解决了我的问题。