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

发布于 2025-01-02 20:07:59 字数 837 浏览 3 评论 0原文

在 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++ 编译器输出一条错误消息:

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

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

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

更新

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

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

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:

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:

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

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

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

Update

I used static keyword 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 static or not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

静待花开 2025-01-09 20:08:00

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

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 -pedantic option. You then should get an error similiar to:

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 constexpr was introduced.

神也荒唐 2025-01-09 20:08:00

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

Yes. Just add the constexpr keyword as the error says.

小猫一只 2025-01-09 20:08:00

我遇到了真正的问题,因为我需要使用相同的代码来使用不同版本的 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 版使用“constexpr”。 0及以上。这是对发生更改的版本的猜测,因为坦率地说,直到 g++ 6.2.1 版本我才注意到这一点。为了正确执行此操作,您可能需要查看 g++ 的次要版本和补丁号,因此请参阅

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

了解可用宏的详细信息。

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

不太好,因为它特定于 gnu 编译器,但我怀疑您可以对其他编译器执行类似的操作。

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

#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 guess at 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

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 -fpermissive flag, but that gives warnings and I like my stuff to compile cleanly.

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

戒ㄋ 2025-01-09 20:08:00

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

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

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 );
    }
};
她说她爱他 2025-01-09 20:07:59

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

,在本例中,类 X 的所有实例的 i 成员由编译器生成的构造函数初始化为 5,并且 >f 成员初始化为 3.12static const 数据成员 j 初始化为 42static constexpr 数据成员 g< /code> 初始化为 9.5

由于 floatdouble 不是整型或枚举类型,因此此类成员必须是 constexpr 或非static > 为了允许类定义中的初始值设定项。

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

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

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 i member of all instances of class X is initialized to 5 by the compiler-generated constructor, and the f member is initialized to 3.12. The static const data member j is initialized to 42, and the static constexpr data member g is initialized to 9.5.

Since float and double are not of integral or enumeration type, such members must either be constexpr, or non-static in order for the initializer in the class definition to be permitted.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文