我想有一类的私人静态常量(在这种情况下,一个形状厂)。
我想有类似的东西。
class A {
private:
static const string RECTANGLE = "rectangle";
}
不幸的是我得到了各种错误从C ++(G ++)编译器,如:
ISO C ++禁止部件的初始化“RECTANGLE”
无效一流初始化非整数类型的静态数据成员的“的std :: string”
错误:制定“矩形”静
这告诉我,这类成员设计的不符合标准的。 你怎么有,而不必使用#define指令的私人字面常量(或者公开)(我想避免数据整体性的uglyness!)
任何帮助表示赞赏。
Answer 1:
你必须定义在类定义之外的静态成员,并提供初始化那里。
第一
// In a header file (if it is in a header file in your case)
class A {
private:
static const string RECTANGLE;
};
然后
// In one of the implementation files
const string A::RECTANGLE = "rectangle";
原先尝试使用(类定义中初始化)语法只与积分和枚举类型允许的。
从你有另一种选择,这非常类似于原来的声明C ++ 17起:内联变量
// In a header file (if it is in a header file in your case)
class A {
private:
inline static const string RECTANGLE = "rectangle";
};
不需要额外的定义。
Answer 2:
在C ++ 11现在你可以这样做:
class A {
private:
static constexpr const char* STRING = "some useful string constant";
};
Answer 3:
中的类定义你只能声明静态成员。 他们必须要在类之外定义 。 对于编译时间积分常数的标准,使您可以“初始化”的成员除外。 它仍然不是一个定义,虽然。 以该地址没有定义工作,例如。
我想提一提,我没有看到使用的std :: string在为const char [] 为常量的利益。 的std :: string是好的,所有的,但它需要动态初始化。 所以,如果你喜欢写东西
const std::string foo = "hello";
在命名空间范围foo的构造将主要的执行开始之前的位置运行,此构造将在堆内存中创建常量“你好”的副本。 除非你真的需要矩形设置为std :: string,你也可以同样写
// class definition with incomplete static member could be in a header file
class A {
static const char RECTANGLE[];
};
// this needs to be placed in a single translation unit only
const char A::RECTANGLE[] = "rectangle";
那里! 没有堆分配,没有复制,没有动态初始化。
干杯,秒。
Answer 4:
这只是额外的信息,但如果你真的想在头文件中的字符串,你可以试试:
class foo
{
public:
static const std::string& RECTANGLE(void)
{
static const std::string str = "rectangle";
return str;
}
};
虽然我怀疑,建议。
Answer 5:
在C ++ 17,你可以使用内联变量 :
class A {
private:
static inline const std::string my_string = "some useful string constant";
};
请注意,这是从不同的abyss.7的回答 :这一个定义了一个实际std::string
对象,而不是const char*
Answer 6:
要使用在级初始化语法中,常数必须由常量表达式初始化整型或枚举类型的静态常量。
这是限制。 因此,在这种情况下,你需要定义在类的外部变量。 从@AndreyT参考answwer
Answer 7:
本标准仅允许静态整型常量类型,初始化。 所以,你需要做的是AndreyT解释。 然而,将在通过下一个标准是可用的新成员初始化语法 。
Answer 8:
可能只是做:
static const std::string RECTANGLE() const {
return "rectangle";
}
要么
#define RECTANGLE "rectangle"
Answer 9:
您可以去的const char*
上述方案中,但随后如果需要串的时候,你将有大量的开销。
在另一方面,静态字符串需要动态初始化,因此,如果你想另一个全局/静态变量的初始化过程中使用它的价值,你会打的初始化顺序的问题。 为了避免这种情况,最便宜的东西是通过一个getter,如果你的对象初始化与否,检查访问静态字符串对象。
//in a header
class A{
static string s;
public:
static string getS();
};
//in implementation
string A::s;
namespace{
bool init_A_s(){
A::s = string("foo");
return true;
}
bool A_s_initialized = init_A_s();
}
string A::getS(){
if (!A_s_initialized)
A_s_initialized = init_A_s();
return s;
}
请记住,只使用A::getS()
因为任何一个线程可以通过才开始main()
并A_s_initialized
之前初始化main()
你并不需要,甚至在多线程环境锁。 A_s_initialized
默认为0(动态初始化之前),所以如果你用getS()
s的初始化之前,您安全地调用init函数。
顺便说一下,在上面的回答是:“ 静态常量的std :: string矩形()const的 ”,静态函数不能是const
,因为他们无法改变状态,如果任何对象反正(有没有这个指针)。
Answer 10:
类的静态变量可以在头声明 ,但必须在一个.cpp文件中定义 。 这是因为只能有一个静态变量的情况下,编译器不能决定其中产生的目标文件,把它,所以你必须做出决定,而不是。
为了保持一个静态值的定义与在C ++ 11的声明可以使用嵌套静态结构。 在这种情况下静态部件是结构,并且具有在一个cpp文件中定义的,但这些值在头中。
class A
{
private:
static struct _Shapes {
const std::string RECTANGLE {"rectangle"};
const std::string CIRCLE {"circle"};
} shape;
};
相反,初始化各个成员的整体静态结构初始化中的.cpp:
A::_Shapes A::shape;
该值与访问
A::shape.RECTANGLE;
或者 - 因为成员是私有的,并打算从一个只用 - 与
shape.RECTANGLE;
请注意,这个解决方案仍然从静态变量的初始化顺序的问题的困扰。 当一个静态值用于初始化另一个静态变量,第一可能不被初始化,但。
// file.h
class File {
public:
static struct _Extensions {
const std::string h{ ".h" };
const std::string hpp{ ".hpp" };
const std::string c{ ".c" };
const std::string cpp{ ".cpp" };
} extension;
};
// file.cpp
File::_Extensions File::extension;
// module.cpp
static std::set<std::string> headers{ File::extension.h, File::extension.hpp };
在这种情况下,静态变量标头将包含任一{“”}或{“.H”,“.HPP”},根据由链接器创建初始化的量级上。
正如@提到abyss.7你也可以使用constexpr
如果变量的值可以在编译时计算。 但是,如果你申报你的字符串static constexpr const char*
和程序使用std::string
否则会有负担,因为一个新std::string
对象将被创建每次使用这种恒定的时间:
class A {
public:
static constexpr const char* STRING = "some value";
};
void foo(const std::string& bar);
int main() {
foo(A::STRING); // a new std::string is constructed and destroyed.
}
Answer 11:
快进到2018和C ++ 17。
以上是适当和合法的标准C ++公民。 它可以变得容易参与任何和所有的std ::算法,容器,公用设施和这样的。 例如:
// test the resilience
auto return_by_val = []() {
auto return_by_val = []() {
auto return_by_val = []() {
auto return_by_val = []() {
return STANDARD::compiletime_static_string_view_constant();
};
return return_by_val();
};
return return_by_val();
};
return return_by_val();
};
// actually a run time
_ASSERTE(return_by_val() == "compile time");
// compile time
static_assert(
STANDARD::compiletime_static_string_view_constant()
== "compile time"
);
享受标准C ++
文章来源: Static constant string (class member)