在类中定义常量(用于常量表达式)的最佳方法?

时间:2009-04-06 11:07:55

标签: c++ constants

我正在为给定的用例为我的类定义一个常量BUFFER_LENGTH。

//1. Using preprocessor declaration
//#define BUFFER_LENGTH  12

//2.Global constant
//const int BUFFER_LENGTH  = 12;
class MyRequest
{
public:
    //3. Define an in-class constant
    //static const int BUFFER_LENGTH = 12;

    //4. Declare an enum constant
    enum 
    {
        BUFFER_LENGTH = 12
    };

    MyRequest()
    {
        strcpy(mBuffer, "TestString");
        printf("Buffer: %s, BUFFER_LENGTH = %d",mBuffer, BUFFER_LENGTH);
    }
private:
    char mBuffer[BUFFER_LENGTH];
};

我刚刚列出了为类定义常量的不同方法。

1. Using Preprocessor constant
2. Using Global constant
3. Using in-class constant
4. using an enum.

其中,哪个是定义给定用例的常量的最佳方法?我更喜欢使用枚举常量而非其他方法。 还有其他更好的方法,我错过了。

谢谢,

7 个答案:

答案 0 :(得分:10)

枚举类型并不意味着定义数字常量,尽管它在模板元编程中使用了很多(ab)。

如果常量的含义与类纠缠在一起,我会在那里定义它。那你还有两个选择:

 class WithConst {
 public:

     // 1. as a const static member variable
     static const int sc_nNumber = 100; // I can initialize here for
                                        // integral-types only

     // 2. as a static member function - possibly inlined.
     static int sf_nNumber() { return 100; }
 };

第二种选择的优势在于您以后不需要更改任何客户端代码。从注册表或配置文件中读取常量。

答案 1 :(得分:9)

出于维护目的,最好尽可能地限制任何名称的范围(无论是功能,变量还是常量)。所以我建议

static const int BUFFER_LENGTH = 12;

enum { BUFFER_LENGTH = 12 };

里面类定义。

前者没有太大的好处,除了你可以明确控制类型。 enum导致C ++为您选择一个未指定的整数“底层类型” - 如果您的枚举仅包含小值,它可能会小到char,但根据经验,大多数编译器默认使用{ {1}}。

答案 2 :(得分:3)

静态const成员变量是最好的 - 它简洁,完全解决了问题并保证不会与其他类似的类发生冲突(这对于预处理器定义或全局常量来说是非常可能的)。我建议你在CamelCase中声明它,而不是在所有带有不受欢迎的大写字母中,这样它看起来不像特别的东西,而是作为一个普通的类成员,它确实是。

答案 3 :(得分:2)

我在“Thinking in C ++”中读到过去使用过“enum-hack”,因为有些编译器不支持“static const”类成员:
http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter08_023.html

因此,如果您使用的是古老的编译器,或者想要支持它们,请使用enum-hack。 (我不知道他们现在必须不支持静态const)

答案 4 :(得分:1)

我不确定在这种特殊情况下它们是否完全可以互换。由于您将数组成员的大小基于常量,我相信它必须是枚举值。我没有时间在标准中查找,但如果您可以使用int成员作为数组大小,即使它是static const,我会感到惊讶,因为实际值可能不是在标题中可见。

// === in myclass.h
class MyClass {
public:
    static const int MY_SIZE;
private:
    int ary[MY_SIZE];
};

// === in myclass.cpp
/*static*/ const int MyClass::MY_SIZE = 10;

// === in otherclass.cpp
void OtherClass::operation(MyClass& obj) {
    std::cout << "Sizeof(MyClass) = " << sizeof(obj) << std::endl;
}

我不认为编译器可以在没有编译otherclass.cpp的情况下编译myclass.cpp

在大多数其他情况下,我会说使用类静态常量选项,因为它会更加智能地参与类型推导等。我只在真正需要时使用枚举整数常量,或者当它们是真正枚举的常量时(当然)。

修改

我刚看完标准品,而我正在吃午饭(感谢大卫的推动)

  

整数常量表达式只能涉及文字(2.13),枚举器,   const变量或初始化的整数或枚举类型的静态数据成员   用常量表达式(8.5),非类型模板参数的积分或   枚举类型和sizeof表达式。

如果你在声明中提供常量初始化器(或者是那个定义?),看起来常量和枚举都可以工作。

答案 5 :(得分:1)

使用const int可能效率低于使用enum,下面是一个演示此内容的程序。使用Metrowerks CodeWarrior 8.x for Windows编译,它表明将类定义为const int的类的对象占用4个字节的内存,而不是将此常量定义为枚举的类似类:

#include <stdio.h>
#include <stdlib.h>

class foo {
    enum { MY_CONST = 1 };
    int x;
    public:
    foo();
};
class bar {
    const int MY_CONST;
    int x;
    public:
    bar();
};

int main() {
    printf( "%u %u\n", sizeof( foo), sizeof( bar));
    return EXIT_SUCCESS;
}

它产生:“4 8”

添加了构造函数以防止编译器进行积极的优化。因为程序不创建这些类型的对象,所以不必在单独的编译模块中实际定义构造函数。 const int

也是如此

答案 6 :(得分:0)

在阅读之前的帖子时,我注意到没有人提到“命名空间中的枚举”技巧。如果您喜欢枚举,因为您正在使用较旧的编译器(我在VxWorks / Tornado嵌入式编程平台上有过这样的经验),那么请注意:您可以通过在命名空间中放置枚举或(如果命名空间不是命名空间)来避免命名冲突在一个班级内支持。