C ++使用类标记数学表达式

时间:2015-01-07 23:47:00

标签: c++ parsing inheritance subclass tokenize

我试图重新学习有关C ++继承的内容,并编写一个程序,从头开始评估简单的数学表达式(作为字符串)以进行练习,但我遇到了很多问题。我之前唯一的lexing体验是使用OCaml(和Ocamllex / yacc),它在那里有点不同。

无论如何,我创建了一个简单的Token类:

class Token{
    public:
        string type;
        string characters;
};

其中type是一个告诉令牌类型的字符串(加号,减号等),而characters是令牌实际包含的字符串。 从这开始,我为每个标记创建了派生类。这是+:

的那个
class Plus: public Token{
    public:
        Plus(){
            type = "plus";
            characters = "+";
        }
};

MinusTimesDividedByLeftParenthesisRightParenthesisNumber都以相同的方式完成。但是,对于Number,我想添加一个存储令牌值的double,因此它还包含公共变量double value,并且其构造函数设置此值。你可能已经看到问题会出现在这里,我会稍微介绍一下这些问题。

我有一个读取字符串的函数,将其拆分为这些子字符串,并将其存储为字符串向量(因此"3.2 +( -1.83)"将返回带有字符串"3.2"的向量,{{1 },"+""(""-1.83")。我有另一个将它全部转换为Token对象并将其存储为Token向量(因此它像")"那样。)

现在我想拿这个令牌向量并用它做一些事情。 (目标是使用分流码算法将其反转波兰表示法,然后对其进行评估。)但是,我有很多问题,主要是因为我使用的是令牌向量,而且每个它的元素是派生类型的标记。

最大的问题是我无法访问tokens.push_back(LeftParenthesis());类型代币的value元素。我尝试过其他一些事情,例如使用虚拟吸气功能,但它仍然无法正常工作。另一个问题是,我可以通过读取Number元素来判断每个事物的类型是什么类型的唯一方法,这似乎使整个子类的东西毫无意义。

是否有可能继续我开始的方法,或者我应该放弃整个Token类及其子类并只使用字符串?它不会是最糟糕的,因为我一直在学习有关继承的东西,而且我已经得到了所有的错误。

编辑:回应Thomas Matthews: 我正在玩虚拟方法(它们也没有工作),所以这里是实际的Token类和Number:

characters

这是我正在玩的主要方法,它只是接受我制作的随机字符串并尝试将其打印出来,但是通过访问任何数字的class Token{ public: string type; string characters; virtual double getValue(); }; class Number: public Token{ public: double value; Number(string chars){ type = "number"; characters = chars; value = atof(chars.c_str()); } virtual double getValue(){ return value; } }; 元素时这样做:

value

2 个答案:

答案 0 :(得分:2)

问题是你正在使用一个标量向量(vector<Token>)所以每当你尝试将一个派生类粘贴到向量中时,它会创建一个新的Token对象,其值从基础部分复制你的令牌类,其余的被剥夺了。这被称为object slicing,这是C ++的一个微妙问题,那些有更多动态OO语言经验的程序员会遇到这种问题。

在C ++中,继承和面向对象通常只能通过指针和引用来工作。如果你想拥有一个可以容纳Token的任何子类的泛型向量,你需要使用vector<Token *>,以及所有相关的内存管理问题。

答案 1 :(得分:0)

我建议你添加一个方法,将Token的值作为字符串返回。

这将允许您将值转换为数字。

也许您应该考虑的是:

  • 用于令牌的价值是多少?
  • 您是否需要告诉令牌来评估给定的表达式?

一个问题是您可能不希望将所有内容都作为通用令牌处理,或者您可以对通用令牌执行的处理有限。