在C ++中的类声明中初始化const成员

时间:2012-02-04 15:29:27

标签: c++ g++

在PHP和C#中,常量可以在声明时初始化:

class Calendar3
{
    const int value1 = 12;
    const double value2 = 0.001;
}

我有一个仿函数的C ++声明,它与另一个类一起使用来比较两个数学向量:

struct equal_vec
{
    bool operator() (const Vector3D& a, const Vector3D& b) const
    {
        Vector3D dist = b - a;
        return ( dist.length2() <= tolerance );
    }

    static const float tolerance = 0.001;
};

此代码编译时没有遇到g ++问题。现在在C ++ 0x模式(-std = c ++ 0x)中,g ++编译器输出错误消息:

  

错误:'constexpr'需要对非整数类型的静态数据成员'容差'进行类内初始化

我知道我可以在类定义之外定义和初始化这个static const成员。此外,可以在构造函数的初始化列表中初始化非静态常量数据成员。

但有没有办法在类声明中初始化一个常量,就像在PHP或C#中一样?

更新

我使用static关键字只是因为可以在g ++中的类声明中初始化这些常量。我只需要一种方法来初始化类声明中的常量,无论它是否声明为static

5 个答案:

答案 0 :(得分:118)

在C ++ 11中,可以在类声明中初始化非static数据成员,static constexpr数据成员和整数或枚举类型的static const数据成员。 e.g。

struct X {
    int i=5;
    const float f=3.12f;
    static const int j=42;
    static constexpr float g=9.5f;
};

在这种情况下,编译器生成的构造函数将i类的所有实例的X成员初始化为5,并将f成员初始化为3.12static const数据成员j已初始化为42static constexpr数据成员g已初始化为9.5

由于floatdouble不是整数或枚举类型,因此此类成员必须为constexpr或非static才能在课程中使用初始值设定项定义是允许的。

在C ++ 11之前,只有static const整数或枚举类型的数据成员可以在类定义中使用初始值设定项。

答案 1 :(得分:43)

初始化const int类型以外的静态成员变量不是C ++ 11之前的标准C ++。除非您指定-pedantic选项,否则gcc编译器不会向您发出警告(并生成有用的代码)。然后你应该得到类似的错误:

const.cpp:3:36: error: floating-point literal cannot appear in a constant-expression
const.cpp:3:36: warning: ISO C++ forbids initialization of member constant ‘tolerance’ of non-integral type ‘const float’ [-pedantic]

这样做的原因是C ++标准没有规定应该如何实现浮点并留给处理器。为了解决这个问题,引入了其他限制constexpr

答案 2 :(得分:10)

是。只需添加constexpr关键字,如错误所示。

答案 3 :(得分:1)

如果您只需要在一种方法中使用它,则可以将其声明为静态:

struct equal_vec
{
    bool operator() (const Vector3D& a, const Vector3D& b) const
    {
        static const float tolerance = 0.001f;
        Vector3D dist = b - a;
        return ( dist.length2() <= tolerance );
    }
};

答案 4 :(得分:1)

我遇到了这个问题,因为我需要使用相同的代码来编译不同版本的g ++(GNU C ++编译器)。所以我不得不使用一个宏来查看正在使用哪个版本的编译器,然后相应地采取行动,如此

#if __GNUC__ > 5
 #define GNU_CONST_STATIC_FLOAT_DECLARATION constexpr
#else
 #define GNU_CONST_STATIC_FLOAT_DECLARATION const
#endif

GNU_CONST_STATIC_FLOAT_DECLARATION static double yugeNum=5.0;

这将在g ++版本6.0.0之前使用'const'表示所有内容,然后在g ++ 6.0.0及更高版本中使用'constexpr'。这是发生变化的版本的 guess ,因为坦白说我直到g ++版本6.2.1才注意到这一点。要做得对,你可能需要查看g ++的次要版本和补丁号,所以请参阅

https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html

有关可用宏的详细信息。

使用gnu,你也可以坚持在任何地方使用'const'然后使用-fpermissive标志进行编译,但这会发出警告,我喜欢我的东西来干净地编译。

不太好,因为它特定于gnu编译器,但我怀疑你可以和其他编译器做类似的事情。