• 《Effective C++》Item2:尽量以const,enum,inline替换#define



    1. 宏定义

    #define ASPECT_RATIO 1.653

    该宏定义ASPECT_RATIO也许从来没有被编译器看到,也许在编译器开始处理源码之前就已经被预处理器替换了。所以记号名称ASPECT_RATIO有可能没进入符号表(symbol table)中。所以,当你从这个常量得到一个编译错误信息时,这个错误信息可能会提到1.653而不是ASPECT_RATIO,如果这个ASPECT_RATIO被定义在一个非你写的头文件中,那么调试追踪这个错误更是麻烦。在调试阶段,visual stiduo和linux平台的gdb在调试的过程中无法查找定义的宏的值,因为符号表中没有这个符号,因此不能所见即所得,还必须通过阅读代码才能看到。

    2. 使用const定义常量

    解决上面的问题的办法就是,以一个常量替换上面的宏

    const double aspectRatio = 1.653//大写名称通常用于宏,因此这里改变名称写法

    从上面可以看出该常量有类型,double。它作为一个常量,肯定能被编译器看到,当然也就能进入符号表中了,进入了符号表的常量表中。

    3. class专属常量

    为了将常量的scope限制于class内,就必须让它成为class的一个成员;而为了确保此常量最多只有一份实体,必须让他让成为一个static成员。

    class GamePlayer
    {
    private:
        static const int NumTurns = 5;//常量声明式
        int scores[NumTurns];//使用该常量
    };
    

      这里看到的是NumTurns的声明式而非定义式。通常C++要求对所使用的任何东西提供一个定义式,但如果它是个class专属常量又是static且为整数类型(integral type例如ints、chars、bools),则需要特殊处理。只要不取他们的地址,就可以声明并使用他们而无需提供定义式。如果要取某个class专属常量的地址,就必须提供这个专属常量的定义式:

    const int GamePlayer::NumTurns;//NumTurns的定义

    要把这个statement放进一个实现文件而非头文件,同时由于class常量在声明时获得了初值,定义时就不可以再设置初值了。
    下面在举个例子说明用法:

    class MyTest
    {
        //“MyTest::maxNumber1”: 只有静态常量整型数据成员才可以在类中初始化
        //int maxNumber1 = 5;
    
        //“MyTest::maxNumber1”: 只有静态常量整型数据成员才可以在类中初始化
        //const int maxNumber2 = 5;
    
        //“MyTest::maxNumber1”: 只有静态常量整型数据成员才可以在类中初始化
        //static int maxNumber3 = 5;
    
        static const int maxNumber4 = 5;
        static const char cconst = 'A';
    public:
        //“MyTest::maxNumber2”: 必须在构造函数基/成员初始值设定项列表中初始化
        //如果有const常量成员,一定要在构造函数的初始值设定项列表中初始化
        MyTest()
        {
            cout << "MyTest Constructor!" << endl;
            cout << "maxNumber4 = " << maxNumber4<< endl;
            cout << "cconst4 = " << cconst << endl;
        }
    
    };
    

    总结一下:

    对于类的const类型的成员,一定要在构造函数的初始化列表中初始化,不管这个const成员变量是static还是非static的。

    对于static的成员变量,要在.cpp文件中提供一个定义式。对静态成员变量的初始化就在这个定义式中进行,但是后面可以在构造函数等的地方做修改。

  • 相关阅读:
    C# delegate委托的用法
    C# new关键字的使用
    C# abstract抽象类的使用
    C# override关键字的使用
    C# sealed关键字的使用
    C# 虚函数virtual的使用
    Java IO流简介
    SpringBoot中异步请求的使用
    SpringBoot中异步调用的使用
    github
  • 原文地址:https://www.cnblogs.com/stemon/p/4324486.html
Copyright © 2020-2023  润新知