【发布时间】:2026-02-02 09:00:01
【问题描述】:
我知道这类问题已经回答过几次,但我给出的问题背景是为了期待其他一些架构替代方案。
考虑一个类 CExpression:
class CExpression
{
public:
...
private:
vector<CComponent*> components_;
string expression_;
}
CExpression 必须将表示数学表达式(例如“y = x + 5”)的字符串分解为向量(“y”、“=”、“x”、“+”、5)。为此,该向量由 CComponent 指针组成,这些指针可以指向 CVariable、COperator 和 CConstant 类的对象。 显然,CComponent 是一个抽象类,是上述三个类的基类。因此,解析字符串后,向量应该依次包含以下内容(过程的半伪代码):
components_.push_back(new CVariable("y"));
components_.push_back(new COperator('='));
components_.push_back(new CVariable("x"));
components_.push_back(new COperator('+'));
components_.push_back(new CConstant( 5 ));
这里使用多态性是将表达式分解为单个向量(这将有助于将来的解析过程)。但是,某些派生类具有其他类所没有的独特功能,因此无法在基类 (CComponent) 中实现这些功能。
例如,考虑 COperator 类:
class COperator : public CComponent
{
public:
int GetPriority() const { return prority_; }
...
private:
int priority_;
...
}
优先级,表示运算符必须从向量中解析的优先级,对于这个类是唯一的(因此在基类中没有虚函数)。现在让我们来解决问题。
考虑CComponent类(基类):
enum Type { VARIABLE, OPERATOR, CONSTANT };
class CComponent
{
public:
Type GetType() const { return type_; }
...
private:
Type type_;
...
}
Type 对表达式的任何组件都是通用的,它表示组件的类型(例如,如果它是 CVariable,则类型将在构造时设置为 VARIABLE)。
最后,考虑一下这个 CExpression 方法(虚构):
void CExpression::Process()
{
for (int i = 0; i < components_.size(); i++)
{
if (components_[i] -> GetType() == OPERATOR)
{
cout << components_[i] -> GetPriority(); // won't work
}
}
}
其实由于我只能使用指针类型类的方法(除非我是dynamic_cast,我认为这不是最好的方式),我有两个问题:
- 是否有合适的方法来做我想要实现的目标,或者 dynamic_cast 是我唯一的选择?
- 我应该采用完全不同的程序架构来解决这个问题吗?如果是,我该怎么办?
顺便说一句,我知道解释起来可能更简单,但我认为上下文将是解决问题的好帮手。
谢谢!
【问题讨论】:
-
我认为树形结构更适合您想要捕捉的各种表达方式。
-
我想有一些选择:a)您可能需要考虑在基类中使用 all 方法,使无效的方法抛出异常或返回错误它们不适用,b) 您可能要考虑使用 visitor pattern 或 command pattern... 两者都是在通用界面下隐藏不同行为的情况。
-
这是访问者模式的经典案例。
标签: c++ polymorphism