You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++解释器开发:基于虚类运行时类型生成TypeChecked对象的问题

解决方案:利用虚函数工厂或访问者模式实现运行时类型匹配的模板实例化

你的核心问题在于模板类TypeChecked<T>的实例化是编译时确定的,但需要根据ValuableAST*的运行时实际类型创建对应实例。针对解释器AST的场景,有两种成熟的最佳实践:


方案一:虚工厂方法(Clone-with-Type)

给基类ValuableAST添加纯虚函数,让每个派生类负责创建自身对应的TypeChecked<T>实例,利用多态特性在运行时派发正确的创建逻辑。

步骤1:修改基类ValuableAST

添加虚函数clone_with_type,用于生成带类型标记的包装实例:

#include <memory> // 引入智能指针

class ValuableAST
{
public:
    virtual ~ValuableAST() = default;
    virtual bool is_checked() const { return false; }

    enum class ValueType { INTEGER, REAL };

    virtual std::variant<int, double> value() const = 0;
    // 新增:返回带类型标记的包装实例,用智能指针避免内存泄漏
    virtual std::unique_ptr<ValuableAST> clone_with_type(ValueType type) const = 0;
};

步骤2:修改TypeChecked模板类

调整构造函数参数为const T*,避免不安全的const_cast:

template <class T>
requires std::is_base_of_v<ValuableAST, T>
class TypeChecked : public T
{
private:
    ValuableAST::ValueType type_;

public:
    // 改为接受const T*,通过拷贝构造创建底层对象
    explicit TypeChecked(ValuableAST::ValueType type, const T* value)
        : T(*value), type_(type) {}

    ValuableAST::ValueType type() const { return type_; }
    bool is_checked() const override { return true; }

    int get_int() const {
        if (type_ == ValuableAST::ValueType::INTEGER) {
            return std::get<int>(this->value());
        } else {
            throw std::runtime_error("Type error");
        }
    }

    double get_real() const {
        if (type_ == ValuableAST::ValueType::REAL) {
            return std::get<double>(this->value());
        } else {
            throw std::runtime_error("Type error");
        }
    }
};

步骤3:在派生类中实现clone_with_type

以Number类为例:

class Number : public ValuableAST
{
private:
    std::variant<int, double> value_;

public:
    std::variant<int, double> value() const { return value_; }

    explicit Number(int value) : value_(value) {}
    explicit Number(double value) : value_(value) {}
    explicit Number(const Number& number) : value_(number.value_) {} // 显式拷贝构造

    // 实现虚工厂方法
    std::unique_ptr<ValuableAST> clone_with_type(ValueType type) const override {
        return std::make_unique<TypeChecked<Number>>(type, this);
    }
};

步骤4:在目标函数中使用

void function_accepting_valuable_ast(ValuableAST* ast, ValuableAST::ValueType checked_type) {
    // 生成带类型检查标记的实例
    std::unique_ptr<ValuableAST> checked_ast = ast->clone_with_type(checked_type);
    
    // 使用checked_ast,无需手动delete,智能指针自动管理内存
    if (checked_ast->is_checked()) {
        // 后续逻辑
    }
}

方案二:访问者模式(Visitor Pattern)

如果你的解释器需要对AST进行多种操作(如类型检查、代码生成、优化等),访问者模式更适合,它将操作逻辑与AST节点类型解耦。

步骤1:定义访问者接口

class ValuableASTVisitor {
public:
    virtual ~ValuableASTVisitor() = default;
    virtual std::unique_ptr<ValuableAST> visit(const Number* node, ValuableAST::ValueType type) = 0;
    // 为其他派生类添加对应的visit方法
};

步骤2:实现TypeChecked创建者

class TypeCheckedCreator : public ValuableASTVisitor {
public:
    std::unique_ptr<ValuableAST> visit(const Number* node, ValuableAST::ValueType type) override {
        return std::make_unique<TypeChecked<Number>>(type, node);
    }
    // 实现其他派生类的visit方法
};

步骤3:给基类添加accept方法

class ValuableAST {
public:
    // ... 原有代码 ...
    virtual void accept(ValuableASTVisitor& visitor, ValuableAST::ValueType type, std::unique_ptr<ValuableAST>& result) const = 0;
};

步骤4:派生类实现accept

class Number : public ValuableAST {
    // ... 原有代码 ...
    void accept(ValuableASTVisitor& visitor, ValuableAST::ValueType type, std::unique_ptr<ValuableAST>& result) const override {
        result = visitor.visit(this, type);
    }
};

步骤5:在目标函数中使用

void function_accepting_valuable_ast(ValuableAST* ast, ValuableAST::ValueType checked_type) {
    TypeCheckedCreator creator;
    std::unique_ptr<ValuableAST> checked_ast;
    ast->accept(creator, checked_type, checked_ast);
    
    // 使用checked_ast
}

方案对比与选择

  • 虚工厂方法:代码简洁,实现成本低,适合派生类数量少、操作单一的场景,符合AST节点的职责单一原则。
  • 访问者模式:扩展性强,新增操作无需修改AST节点类,适合需要对AST进行多种复杂处理的解释器/编译器场景。
  • 无论哪种方案,都建议使用std::unique_ptr或std::shared_ptr管理动态对象,避免手动内存管理带来的泄漏风险。

内容的提问来源于stack exchange,提问作者Junhui Zhu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 11:54:57