您的位置:首页 > 其它

可以继承的枚举类

2012-10-07 12:31 183 查看
在实现lexer和parser的过程中,要定义token的类型。《编程语言实现模式》中使用的是java代码,直接定义static int TEXT = 1;并且可以在lexer扩展的时候继承到实际使用的lexer里面。但C++定义类的static成员时,必须在外面单独的进行初始化,对这一点不是很爽,在C++11中,实现了enum class,

先看看这个enum class能不能满足要求,例如

enum class TokenType{
_EOF,
TEXT
};

TokenType a = TokenType::TEXT;


那么就可以方便地使用TokenType::TEXT指代类型,只有同是TokenType,才能进行比较。如果要进行扩展,如下

enum class ExprTokenType:public TokenType{
NUMBER,
OP
};


希望新的类型ExprTokenType在TokenType的基础上,添加两种类型,既然是class,继承应该没问题的吧?但编译的时候就报错了。只好放弃这种方式了。

后来想到下面的实现,

class TokenType{
public:
TokenType(){
nameMap = {"_EOF","TEXT"};
}
string Name(int x){
return nameMap.at(x);
}
public:
const static int _EOF = 0; // const static 成员 可以在这里直接初始化,
// 如果只是const修饰,const成员需要在构造函数的初始化列表里面进行赋值
// public成员, 可以像 enum class类似地,使用TokenType.TEXT访问
const static int TEXT = 1;
protected:
vector<string> nameMap;// 可以根据 类型 得到其名称,便于调试,
}TokenType;

class ExprTokenType:public TokenType{
public:
ExprTokenType(){
nameMap.push_back("NUMBER"); // 为新添加的类型添加对应的名称,
nameMap.push_back("OP");
}
public:
const static int NUMBER = 2;
const static int OP = 3;
}ExprTokenType;
// 这里定义一个同名的实例,以后就可以直接使用 类名.类型,
// 如果不这样做的话,或许把它所有的内容都声明为static,也是同样的。


期望的功能都实现了,只是这与enum class不一样,不是类型安全的。不过没关系,能用就已经很好了。

下面是测试代码,

int main(){
cout << "---test enum type---" << endl;
int a = TokenType::TEXT;
cout << "TokenType a:" << a << endl;
cout << "ToeknType a:" << TokenType.Name(a) << endl;
int b = ExprTokenType::OP;
cout << "ExprTokenType b:" << b << endl;
cout << "ExprToeknType b:" << ExprTokenType.Name(b) << endl;
b = ExprTokenType::TEXT;
cout << "ExprTokenType b:" << b << endl;
cout << "ExprToeknType b:" << ExprTokenType.Name(b) << endl;

if(a==b)
cout << "test done." << endl;
return 0;
}


需要注意的是,编译的时候需要添加C++11的支持,g++ -std=c++0x .....

应该有更好的形式来实现吧,希望能与大家交流。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐