可以在定义(.cpp文件)中初始化静态float constexpr成员

时间:2019-07-16 14:05:22

标签: c++ static floating-point

我想在类的定义中初始化我的私有静态成员“ 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旨在初始化类的实例,而静态成员应该已经初始化为int中的全局元素。 “形状”命名空间。

我想这是因为链接器试图在标头中初始化成员,因为它必须在预处理阶段完成,而以后要使用.cpp文件。

1 个答案:

答案 0 :(得分:0)

使用static constexpr成员,您不能在类定义中放弃初始化程序。 constexpr变量必须在声明时进行初始化,因为可以在常量表达式中声明它后使用它。 C ++ 11标准的[class.static.data]/3中对此进行了详细说明

  

如果非易失性const静态数据成员是整数或枚举类型,则其在类定义中的声明可以指定大括号或相等初始化器,其中每个作为赋值表达式的初始化子句都是常量表达式([expr.const])。 可以使用constexpr说明符在类定义中声明文字类型的静态数据成员;如果是这样,则其声明应指定一个花括号或等于初始化器,其中作为赋值表达式的每个初始化器子句都是一个常量表达式。 [注意:在这两种情况下,该成员都可能以常量形式出现表达式。 —结束说明] 如果该成员在程序中被odd使用([basic.def.odr]),并且该命名空间范围定义中不应包含初始化程序,则该成员仍应在命名空间范围中定义。

强调我的

因此,您的代码必须是

// .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的新文本是

  

如果非易失性非内联const静态数据成员是整数或枚举类型,则其在类定义中的声明可以指定大括号或相等初始化器,其中每个初始化器子句都是一个赋值表达式是一个常量表达式([expr.const])。如果在程序中对成员进行了odr-used([basic.def.odr]),则该成员仍应在命名空间范围内定义,并且命名空间范围定义不应包含初始化程序。 可以在类定义中定义内联静态数据成员,并可以指定大括号或等于初始化器。如果使用constexpr说明符声明了该成员,则可以在没有初始化程序的命名空间范围内对其进行重新声明(不建议使用此用法;请参见[depr.static.constexpr])。其他静态数据成员的声明中不得指定大括号或相等的初始化程序。

强调我的

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

  

constexpr说明符应仅应用于变量或变量模板的定义或函数或函数模板的声明。年代说明符应仅应用于函数或函数模板的声明。 用constexpr或consteval说明符声明的函数或静态数据成员隐式是内联函数或变量([dcl.inline])。如果任何函数或函数模板的声明具有constexpr或consteval说明符,则其所有声明应包含相同的说明符。

强调我的