c++ - 在定义(.cpp 文件)中初始化 static float constexpr 成员是否可能

标签 c++ static floating-point

我想在类的定义中初始化我的私有(private)静态成员“pi”,以便更好地整理我的代码,以便在 .cpp 文件中进行初始化。

当我尝试时,出现此错误:“声明 constexpr 静态数据成员 'pi' 需要初始化程序”

我使用的是 CLion 2018.3.4 和 C++ 11。

我尝试解决,唯一的解决方案是在声明中初始化成员。

Stack Overflow 上的其他答案为我提供了更好的知识,但没有回答我的问题。

//.h文件

class Shape {
public:
    virtual void getArea();

private:
    static constexpr float pi; // the error shows up here
};

//.cpp 文件

#include "Shape.h"

const float Shape::pi = 3.14; //here I don't exactly know why it does not require constexpr, but it's fine even with and without const 

// what I think this is equivalent to (in .h file)
static constexpr float pi = 3.14;

我期望它能像我在声明中分配“3.14”一样工作。

我没有定义构造函数,在这种情况下我知道它不会工作,因为 c'tor 旨在初始化类的实例,而静态成员应该已经初始化为全局元素“Shape”命名空间。

我认为发生的情况是链接器尝试初始化 header 中的成员,因为它必须在预处理阶段完成,而稍后使用 .cpp 文件。

最佳答案

对于static constexpr 成员,您不能在类定义中省略初始值设定项。 constexpr 变量必须在声明时初始化,因为它可以在常量表达式中声明后使用。这在[class.static.data]/3中有详细介绍。 C++11 标准

If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression ([expr.const]). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. — end note ] The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer.

强调我的

因此,您的代码需要是

// .h file
class Shape {
public:
    virtual void getArea();

private:
    static constexpr float pi = 3.14; // we initialize here so it can be used.
};

// .cpp file
constexpr float Shape::pi; // we define here so it can be odr-used

请注意,这在 C++17 中已发生变化。随着介绍inline variables static constexpr 成员变量不再需要在类外部定义。编译器将为您处理它并确保仅存在该对象的单个定义。如果需要,您仍然可以定义成员,但该功能已弃用,并且很可能会在未来的标准修订版中删除。 [class.static.data]/3 的新文本是

If a non-volatile non-inline const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression ([expr.const]). The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer. An inline static data member may be defined in the class definition and may specify a brace-or-equal-initializer. If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see [depr.static.constexpr]). Declarations of other static data members shall not specify a brace-or-equal-initializer.

强调我的

[dcl.constexpr]/1表示 static constexpr 变量是隐式内联的

The constexpr specifier shall be applied only to the definition of a variable or variable template or the declaration of a function or function template. The consteval specifier shall be applied only to the declaration of a function or function template. A function or static data member declared with the constexpr or consteval specifier is implicitly an inline function or variable ([dcl.inline]). If any declaration of a function or function template has a constexpr or consteval specifier, then all its declarations shall contain the same specifier.

强调我的

关于c++ - 在定义(.cpp 文件)中初始化 static float constexpr 成员是否可能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57059159/

相关文章:

c++ - float 精度

math - float 学有问题吗?

c++ - boost元组导致boost绑定(bind)/boost函数出现问题?

c++ - "normal"数据到底是什么?(direct3d 11,c++)

java - 用静态 block 覆盖静态字段是不好的做法吗?

c++ - 类中的静态函数和数组

c++ - 带有 vector 成员的结构的 istream

c++ - 通用 Makefile 忽略变量

java - 如何从另一个类的静态方法更改静态变量的值

bash - 管道 awk 输出以添加到循环内的变量