• 可以继承的枚举类


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

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

  • 相关阅读:
    css+js实现的一个导航栏
    各类插件的网页库
    vue构建项目全过程
    手把手教你使用Git
    创建git库
    VUE.JS的安装
    reset.css 初始化
    分布式事务方案
    线程池的参数
    每秒上千订单场景下,如何对分布式锁的并发能力进行优化
  • 原文地址:https://www.cnblogs.com/Frandy/p/enum_class_inherit_class.html
Copyright © 2020-2023  润新知