C ++避免向下转发

时间:2014-06-21 21:36:44

标签: c++ inheritance polymorphism subclass downcast

我需要解析源代码。我已经确定了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,每个子类都会覆盖,但我仍然需要将基类指针转发到子类指针,以便我可以访问子类的特定数据。

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

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

1 个答案:

答案 0 :(得分:5)

您有三种选择。每种解决方案都有其优点和缺点。

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

    这将是&#34;最纯粹的面向对象&#34;解。缺点是逻辑倾向于在基类和子类之间传播,这使得它更难以遵循。它也可能导致类增长相当大。但是编制者/口译员通常不会采取那么多行动来解决这个问题。

  • 使用Visitor Pattern

    有一个接口TokenVisitorvisit方法重载了令牌子类型和accept(TokenVisitor&) Token方法,每个子类都会覆盖这些方法来调用{的适当重载{1}}。

    您现在需要知道界面中完整的令牌类型集,但它允许保持类合理地小,并按行动分组,逻辑通常更容易遵循。

  • 使用受歧视的联合,例如Boost.Variant

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