问题梗概如标题所述。
在今天实现Token类的时候,遇到的问题。
我希望将Token类设定为immutable属性的,这样实现的方式是将这个类内的所有字段均设置为const型,同时每个字段均为public可访问型。
类内主要有两个字段:mark(枚举类型,用于标记当前Token对象所代表的具体类型,比如INT,CHAR等);匿名union字段,用于存储mark标记下对应的具体值。
当我把两个字段均设置为const型时,拷贝构造器将会面临一些实现上的困难。
简言之,如果这样来写拷贝构造器:
1 class Token { 2 public: 3 const Mark mark; 4 const union { 5 int ival; 6 char cval; 7 } 8 9 Token(const Token &tk) : mark(tk.mark) { 10 if (tk.mark == INT) { 11 ival = tk.ival; 12 } else if (tk.mark == CHAR) { 13 cval = tk.cval; 14 } 15 } // 存在问题 16 17 Token &operator=(const Token &tk) { 18 // 问题类似 19 } 20 ... 21 };
将会因为const字段无法被赋值而报错。
问题的关键就在于,只有确定了mark的具体值时,才能确定应该拷贝匿名union字段的哪个字段值。
暂时未解决该问题,望读者分享自己的想法。
此外,在编译过程中,遇到了clang的如下警告:
warning: all paths through this function will call itself
[-Winfinite-recursion]
1 warning generated.
报错代码:
1 std::ostream &operator<<(std::ostream &os, const Token &tok) { 2 os << "Tk:" << tok.getMark() << " " << tok.getLexeme(); 3 return os; 4 }
其中getMark方法定义如下:
1 Mark Token::getMark() const { 2 return mark; 3 }
即直接将mark字段值返回(该字段是一个枚举类类型值,枚举类为Mark)。
此时执行Warning代码,会发现程序循环输出"Tk:"(Tk:Tk:Tk:Tk:....)。
此时,需要将枚举类型值强制转换为int型,实现正常输出。修改后的代码:
1 std::ostream &operator<<(std::ostream &os, const Token &tok) { 2 os << "Tk:" << (int)tok.getMark() << " " << tok.getLexeme(); 3 return os; 4 }
至于为何出现这样的问题,初步猜测是和枚举类的内部实现有关。
针对出现这个问题的具体原因,欢迎分享想法。
2019.09.19
Modnar