【发布时间】:2011-02-06 00:36:00
【问题描述】:
我有课
class foo {
public:
foo();
foo( int );
private:
static const string s;
};
在源文件中初始化字符串s的最佳位置在哪里?
【问题讨论】:
标签: c++ static initialization constants
我有课
class foo {
public:
foo();
foo( int );
private:
static const string s;
};
在源文件中初始化字符串s的最佳位置在哪里?
【问题讨论】:
标签: c++ static initialization constants
one 编译单元(通常是 .cpp 文件)中的任何地方都可以:
foo.h
class foo {
static const string s; // Can never be initialized here.
static const char* cs; // Same with C strings.
static const int i = 3; // Integral types can be initialized here (*)...
static const int j; // ... OR in cpp.
};
foo.cpp
#include "foo.h"
const string foo::s = "foo string";
const char* foo::cs = "foo C string";
// No definition for i. (*)
const int foo::j = 4;
(*) 如果i 用于除整型常量表达式以外的代码,则必须在类定义之外定义i(如j 是)。有关详细信息,请参阅下面 David 的评论。
【讨论】:
i 必须在 cpp 中定义。 §9.4.2/4 如果静态数据成员是 const 整数或 const 枚举类型,它在类定义中的声明可以指定一个常量初始化器,它应该是一个整数常量表达式 (5.19)。在这种情况下,成员可以出现在整型常量表达式中。如果在程序中使用该成员,则该成员仍应在名称空间范围内定义,并且名称空间范围定义不应包含初始值设定项。
i 必须在 用于除整数常量表达式之外的其他地方时才被定义,对吧?在这种情况下,您不能说存在错误,因为没有足够的上下文可以确定——或者严格来说,如果没有其他代码,上述示例是正确的。现在我非常感谢您的评论(+1),我自己还在学习!所以我会尝试在答案中澄清这一点,如果它更好,请告诉我......
int f() { return 42; } class foo { static const int i = f(); /* Error! */ } 注意 C++11 允许调用 'constexpr' 函数:constexpr int f() { return 42; } class foo { static const int i = f(); /* Ok */ }
静态成员需要在文件范围或适当命名空间的 .cpp 翻译单元中初始化:
const string foo::s( "my foo");
【讨论】:
自 C++17 起,inline 说明符也适用于变量。您现在可以在类定义中定义静态成员变量:
#include <string>
class foo {
public:
foo();
foo( int );
private:
inline static const std::string s { "foo" };
};
【讨论】:
在同一命名空间内的翻译单元中,通常在顶部:
// foo.h
struct foo
{
static const std::string s;
};
// foo.cpp
const std::string foo::s = "thingadongdong"; // this is where it lives
// bar.h
namespace baz
{
struct bar
{
static const float f;
};
}
// bar.cpp
namespace baz
{
const float bar::f = 3.1415926535;
}
【讨论】:
只有整数值(例如,static const int ARRAYSIZE)在头文件中被初始化,因为它们通常在类头中用于定义诸如数组大小之类的东西。非整数值在实现文件中初始化。
【讨论】: