C避免向下转发

我需要解析源代码.我已经确定了3种不同类型的标记:符号(运算符,关键字),litterals(整数,字符串等)和标识符.

我已经有了以下设计,其中有一个跟踪子类类型的基类,因此可以使用基类指针对其进行下载:

class Token
{
    type_e type; // E_SYMBOL, E_LITTERAL, E_TOKEN
};

class Symbol : public Token
{
    const symbol_e symbol;
};

class Litteral : public Token
{
    const Value value;
};

class Identifier : public Token
{
    const std::string name;
};

我需要将这些类存储在一个令牌数组中,这就是为什么我需要它们有一个共同的基类.然后我像这样使用它们:

if( cur->type == E_SYMBOL && static_cast< const Symbol * >( cur )->symbol == E_LPARENT )
{
    // ...
}

我可以创建虚函数isSymbol,isLitteral,isIdentifer,每个子类都会覆盖,但我仍然需要将基类指针向下转换为子类指针,以便我可以访问子类的特定数据.

人们说向下转换意味着界面可能存在缺陷,并且它使语法非常沉重,所以我想找到另一种方式,但我不能.有些人建议访问者模式,但我担心这会无用地复杂化代码,我甚至不明白我如何使用访问者模式来解决这个问题.

有人可以帮忙吗?谢谢 :)

解决方法:

你有三个选择.每种解决方案都有其优点和缺点.

>将逻辑放入令牌类中,因此调用代码不需要知道它正在处理哪种令牌.

这将是“最纯粹的面向对象”解决方案.缺点是逻辑倾向于在基类和子类之间传播,这使得它更难以遵循.它也可能导致类增长相当大.但是编译器/解释器通常没有那么多的操作会成为问题.
>使用Visitor Pattern.

这是一个接口TokenVisitor,其中访问方法为令牌子类型重载,并在令牌上接受(TokenVisitor&)方法,每个子类将覆盖该方法以调用适当的访问重载.

您现在需要知道接口中的完整令牌类型集,但它允许保持类合理地小,并按行动分组逻辑通常更容易遵循.
>使用有区别的联盟,例如Boost.Variant.

这根本不是面向对象的.它将导致在整个地方切换类型,并可能看起来很难看.但由于逻辑总是在一起,因此通常更容易理解,特别是对于那些不理解代码背后的想法的人.

上一篇:动态方法调度如何在Java中工作


下一篇:c – boost序列化异常:未注册的类,序列化多态基本问题