簡體   English   中英

使用模板邏輯在運行時從基類轉換為派生類

[英]Convert from base to derived class at runtime using template logic

我正在編寫一個小型數據庫,似乎遇到了問題。 我有 3 種Statement類型(每個類型對應於CREATEINSERTSELECT 。這些類型的定義是:

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_createexecute_insertexecute_select ),它們分別將派生類作為參數( CreateStatementInsertStatementSelectStatement )。 這樣執行函數就可以在解析時使用存儲在派生類對象中的信息。

我可以使用某種模板邏輯來調用適當的執行函數,還是在解析后返回基類后丟失了派生類的信息? 我嘗試做一些事情,如:

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對象的引用,也將毫不費力地調用正確的派生方法。 我假設返回一個布爾值來表示成功。

這意味着您需要使用對語句的引用(或指針)。 這是多態繼承的主要優勢——能夠以相同的方式對不同派生的對象進行操作,而不必擔心它們究竟是什么。

動態調度:

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() { ... }
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM