c++实现解释器模式完整源代码(附带源码)
一、项目背景详细介绍
在软件工程中,我们经常会遇到这样一类问题:需要对某种“语言”或“规则”进行解析和执行。这里的语言并不一定是像 C++、Java 这样的通用编程语言,它可能是:
-
数学表达式(如:
a + b - c) -
规则引擎中的条件表达式(如:
age > 18 && vip == true) -
SQL 的子集
-
正则表达式
-
配置文件中的规则描述语言(DSL)
如果每次遇到这种需求都通过大量 if-else 或 switch 来硬编码解析逻辑,代码将迅速变得:
-
难以维护
-
难以扩展
-
可读性极差
解释器模式(Interpreter Pattern) 正是为了解决这类问题而诞生的。
解释器模式属于 行为型设计模式,它的核心思想是:
将一种语言的文法表示为一个类层次结构,并使用这些类来解释语言中的句子。
在本项目中,我们将使用 C++ 实现一个简易数学表达式解释器,用于解析并计算类似如下的表达式:
a + b - c
通过该示例,你将完整理解解释器模式在真实代码中的结构和落地方式。
二、项目需求详细介绍
本项目的功能需求如下:
-
支持基本的变量表达式(如:
a、b、c) -
支持加法运算(
+) -
支持减法运算(
-) -
使用上下文(Context)存储变量与其对应的值
-
使用解释器模式的标准结构进行设计
-
代码结构清晰,符合教学与博客使用场景
非功能性需求:
-
代码必须具备良好的可读性
-
各个类职责清晰
-
易于扩展(如未来增加乘法、除法)
三、相关技术详细介绍
3.1 解释器模式核心角色
解释器模式通常包含以下几个核心角色:
1. AbstractExpression(抽象表达式)
-
声明一个解释操作
interpret() -
所有具体表达式的父类
2. TerminalExpression(终结符表达式)
-
实现与文法中的终结符相关的解释操作
-
本例中:变量表达式
3. NonTerminalExpression(非终结符表达式)
-
表示语法规则中的非终结符
-
本例中:加法表达式、减法表达式
4. Context(上下文)
-
保存解释器之外的一些全局信息
-
本例中:变量与其对应的值
3.2 C++ 面向对象特性
本项目将使用到以下 C++ 技术点:
-
抽象基类(纯虚函数)
-
多态
-
智能指针(
std::shared_ptr) -
STL 容器(
std::map、std::string)
四、实现思路详细介绍
整体实现思路如下:
-
定义一个抽象表达式类
Expression -
所有表达式都继承自
Expression,并实现interpret()方法 -
使用
Context保存变量与值的映射关系 -
通过组合(而非继承)来构建复杂表达式树
-
最终通过调用根节点的
interpret()方法完成解释和计算
表达式:
a + b - c
其对应的抽象语法树结构为:
(-)
/ \
(+) c
/ \
a b
五、完整实现代码
说明:所有代码放在一个代码块中,不同文件使用注释区分
/************************************************
* 文件:Expression.h
************************************************/
#include <iostream>
#include <string>
#include <map>
#include <memory>
class Context {
private:
std::map<std::string, int> variables;
public:
void setVariable(const std::string& name, int value) {
variables[name] = value;
}
int getVariable(const std::string& name) const {
auto it = variables.find(name);
if (it != variables.end()) {
return it->second;
}
throw std::runtime_error("Variable not found: " + name);
}
};
// 抽象表达式
class Expression {
public:
virtual ~Expression() {}
virtual int interpret(const Context& context) const = 0;
};
/************************************************
* 文件:TerminalExpression.h
************************************************/
class VariableExpression : public Expression {
private:
std::string name;
public:
explicit VariableExpression(const std::string& varName)
: name(varName) {}
int interpret(const Context& context) const override {
return context.getVariable(name);
}
};
/************************************************
* 文件:NonTerminalExpression.h
************************************************/
class AddExpression : public Expression {
private:
std::shared_ptr<Expression> left;
std::shared_ptr<Expression> right;
public:
AddExpression(std::shared_ptr<Expression> l,
std::shared_ptr<Expression> r)
: left(l), right(r) {}
int interpret(const Context& context) const override {
return left->interpret(context) + right->interpret(context);
}
};
class SubtractExpression : public Expression {
private:
std::shared_ptr<Expression> left;
std::shared_ptr<Expression> right;
public:
SubtractExpression(std::shared_ptr<Expression> l,
std::shared_ptr<Expression> r)
: left(l), right(r) {}
int interpret(const Context& context) const override {
return left->interpret(context) - right->interpret(context);
}
};
/************************************************
* 文件:main.cpp
************************************************/
int main() {
// 创建上下文并设置变量
Context context;
context.setVariable("a", 10);
context.setVariable("b", 5);
context.setVariable("c", 3);
// 构建表达式 a + b - c
std::shared_ptr<Expression> exprA = std::make_shared<VariableExpression>("a");
std::shared_ptr<Expression> exprB = std::make_shared<VariableExpression>("b");
std::shared_ptr<Expression> exprC = std::make_shared<VariableExpression>("c");
std::shared_ptr<Expression> addExpr =
std::make_shared<AddExpression>(exprA, exprB);
std::shared_ptr<Expression> subExpr =
std::make_shared<SubtractExpression>(addExpr, exprC);
// 解释并输出结果
int result = subExpr->interpret(context);
std::cout << "Result: " << result << std::endl;
return 0;
}
六、代码详细解读(仅解读方法作用)
6.1 Context::setVariable
用于向上下文中注册变量名及其对应的值。
6.2 Context::getVariable
根据变量名获取对应的值,如果变量不存在则抛出异常。
6.3 Expression::interpret
解释器模式的核心接口,用于定义所有表达式的统一解释行为。
6.4 VariableExpression::interpret
从上下文中读取变量的值,属于终结符表达式。
6.5 AddExpression::interpret
递归解释左右子表达式,并返回它们的加法结果。
6.6 SubtractExpression::interpret
递归解释左右子表达式,并返回它们的减法结果。
七、项目详细总结
通过本项目,我们完整实现了一个基于 解释器模式 的 C++ 示例。该模式的优点包括:
-
文法规则清晰
-
表达式结构可扩展
-
符合开闭原则
但其缺点也同样明显:
-
类数量容易膨胀
-
复杂文法实现成本较高
因此,解释器模式适合:
-
DSL
-
规则引擎
-
表达式计算
而不适合复杂、通用语言的解析。
八、项目常见问题及解答
Q1:为什么不用 if-else?
A:if-else 不利于扩展,违反开闭原则。
Q2:解释器模式一定要用递归吗?
A:通常是的,因为表达式天然是树结构。
Q3:是否可以不用智能指针?
A:可以,但会增加内存管理复杂度,不利于教学。
九、扩展方向与性能优化
-
增加乘法、除法表达式
-
增加括号支持
-
结合工厂模式构建表达式树
-
使用缓存机制减少重复解释
-
与词法分析器、语法分析器结合,构建完整 DSL
更多推荐

所有评论(0)