现在的位置: 首页 > 综合 > 正文

可以继承的枚举类

2012年12月09日 ⁄ 综合 ⁄ 共 1547字 ⁄ 字号 评论关闭

在实现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 .....

应该有更好的形式来实现吧,希望能与大家交流。

抱歉!评论已关闭.