在C ++的类声明中初始化const成员
在PHP和C#中,常量可以在声明时初始化:
class Calendar3 { const int value1 = 12; const double value2 = 0.001; }
我有以下C ++声明与另一个类用于比较两个math向量:
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'需要静态数据成员在类中初始化非整数types的'tolerance'
我知道我可以在类定义之外定义和初始化这个static const
成员。 而且,一个非静态的常量数据成员可以在构造函数的初始化列表中初始化。
但有没有什么办法可以在类声明中初始化一个常量,就像在PHP或C#中一样?
更新
我使用static
关键字只是因为可以在g ++的类声明中初始化这样的常量。 我只需要一种方法来初始化类声明中的一个常量,不pipe它是否声明为static
。
在C ++ 11中,可以在类声明中初始化非static
数据成员, static constexpr
数据成员和整型或枚举types的static const
数据成员。 例如
struct X { int i=5; const float f=3.12f; static const int j=42; static constexpr float g=9.5f; };
在这种情况下,类X
的所有实例的i
成员被编译器生成的构造函数初始化为5
,并且f
成员被初始化为3.12
。 static const
数据成员j
初始化为42
, static constexpr
数据成员g
初始化为9.5
。
由于float
和double
不是整型或枚举types,因此这些成员必须是constexpr
或非static
才能允许类定义中的初始化器。
在C ++ 11之前,只有整型或枚举types的static const
数据成员可以在类定义中具有初始化器。
初始化除const inttypes以外的静态成员variables不是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
被介绍。
是。 只要添加constexpr
关键字的错误说。
如果你只需要一个方法,你可以在本地静态声明它:
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 ); } };
我遇到了这个问题,因为我需要使用相同的代码来编译不同版本的g ++(GNU C ++编译器)。 所以我不得不使用一个macros来查看哪个版本的编译器正在被使用,然后相应地执行,就像这样
#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'。 这是在发生变化的版本的猜测 ,因为坦率地说,我没有注意到,直到g ++版本6.2.1。 要做到这一点,你可能要看g ++的次版本和补丁号,所以看看
https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
有关可用macros的详细信息。
用gnu,你也可以坚持使用'const',然后用-fpermissive
标志来编译,但是这会给出警告,我喜欢我的东西来干净地编译。
不是很好,因为它是GNU编译器特有的,但我怀疑你可以做类似于其他编译器。
那么,不完全是一个直接的答案,但不使用macros的具体原因?
#define tolerance 0.001 struct equal_vec { bool operator() (const Vector3D& a, const Vector3D& b) const { Vector3D dist = b - a; return ( dist.length2() <= tolerance ); } };
不完美的C#的做法,但恕我直言,完全合法的C + +。