我试图重新学习有关C ++继承的内容,并编写一个程序,从头开始评估简单的数学表达式(作为字符串)以进行练习,但我遇到了很多问题。我之前唯一的lexing体验是使用OCaml(和Ocamllex / yacc),它在那里有点不同。
无论如何,我创建了一个简单的Token类:
class Token{
public:
string type;
string characters;
};
其中type
是一个告诉令牌类型的字符串(加号,减号等),而characters
是令牌实际包含的字符串。
从这开始,我为每个标记创建了派生类。这是+:
class Plus: public Token{
public:
Plus(){
type = "plus";
characters = "+";
}
};
Minus
,Times
,DividedBy
,LeftParenthesis
,RightParenthesis
和Number
都以相同的方式完成。但是,对于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
答案 0 :(得分:2)
问题是你正在使用一个标量向量(vector<Token>
)所以每当你尝试将一个派生类粘贴到向量中时,它会创建一个新的Token对象,其值从基础部分复制你的令牌类,其余的被剥夺了。这被称为object slicing,这是C ++的一个微妙问题,那些有更多动态OO语言经验的程序员会遇到这种问题。
在C ++中,继承和面向对象通常只能通过指针和引用来工作。如果你想拥有一个可以容纳Token
的任何子类的泛型向量,你需要使用vector<Token *>
,以及所有相关的内存管理问题。
答案 1 :(得分:0)
我建议你添加一个方法,将Token的值作为字符串返回。
这将允许您将值转换为数字。
也许您应该考虑的是:
一个问题是您可能不希望将所有内容都作为通用令牌处理,或者您可以对通用令牌执行的处理有限。