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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9141950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 12:22:21  来源:igfitidea点击:

Initializing const member within class declaration in C++

c++g++

提问by ezpresso

In PHP and C# the constants can be initialized as they are declared:

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

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

I have the following C++ declaration of a functor which is used with another class to compare two math vectors:

我有一个函子的以下 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;
};

This code compiled without problems with g++. Now in C++0x mode (-std=c++0x) the g++ compiler outputs an error message:

这段代码用g++编译没有问题。现在在 C++0x 模式 (-std=c++0x) 下,g++ 编译器输出错误消息:

error: ‘constexpr' needed for in-class initialization of static data member ‘tolerance' of non-integral type

错误:非整数类型的静态数据成员“公差”的类内初始化需要“constexpr”

I know I can define and initialize this static constmember outside of the class definition. Also, a non-static constant data member can be initialized in the initializer list of a constructor.

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

But is there any way to initialize a constant within class declaration just like it is possible in PHP or C#?

但是有没有什么方法可以像在 PHP 或 C# 中一样在类声明中初始化一个常量?

Update

更新

I used statickeyword just because it was possible to initialize such constants within the class declaration in g++. I just need a way to initialize a constant in a class declaration no matter if it declared as staticor not.

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

回答by Anthony Williams

In C++11, non-staticdata members, static constexprdata members, and static constdata members of integral or enumeration type may be initialized in the class declaration. e.g.

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

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

In this case, the imember of all instances of class Xis initialized to 5by the compiler-generated constructor, and the fmember is initialized to 3.12. The static constdata member jis initialized to 42, and the static constexprdata member gis initialized to 9.5.

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

Since floatand doubleare not of integral or enumeration type, such members must either be constexpr, or non-staticin order for the initializer in the class definition to be permitted.

由于floatdouble不是整数或枚举类型,因此此类成员必须是constexpr或非static,以便允许类定义中的初始化程序。

Prior to C++11, only static constdata members of integral or enumeration type could have initializers in the class definition.

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

回答by Florian

Initializing static member variables other than const int types is not standard C++ prior C++11. The gcc compiler will not warn you about this (and produce useful code nonetheless) unless you specify the -pedanticoption. You then should get an error similiar to:

初始化 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]

The reason for this is that the C++ standard does not specifiy how floating point should be implemented and is left to the processor. To get around this and other limitations constexprwas introduced.

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

回答by StilesCrisis

Yes. Just add the constexprkeyword as the error says.

是的。只需constexpr按照错误说明添加关键字即可。

回答by nilesOien

I ran into real problems with this, because I need the same code to compile with differing versions of g++ (the GNU C++ compiler). So I had to use a macro to see which version of the compiler was being used, and then act accordingly, like so

我遇到了真正的问题,因为我需要相同的代码来编译不同版本的 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;

This will use 'const' for everything before g++ version 6.0.0 and then use 'constexpr' for g++ version 6.0.0 and above. That's a guessat the version where the change takes place, because frankly I didn't notice this until g++ version 6.2.1. To do it right you may have to look at the minor version and patch number of g++, so see

这将对 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

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

for the details on the available macros.

有关可用宏的详细信息。

With gnu, you could also stick with using 'const' everywhere and then compile with the -fpermissiveflag, but that gives warnings and I like my stuff to compile cleanly.

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

Not great, because it's specific to gnu compilers, butI suspect you could do similar with other compilers.

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

回答by Peter Wood

If you only need it in the one method you can declare it locally static:

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

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 );
    }
};