我有以下可用代码:
#include <string>
#include <iostream>
class A {
public:
const std::string test = "42";
//static const std::string test = "42"; // fails
};
int main(void){
A a;
std::cout << a.test << '\n';
}
有没有一个很好的理由,为什么不能将测试设置为
static const
?我理解在c++11之前它受标准限制。我认为c++11引入了类内初始化,使其更加友好。我也知道对于整数类型已经有这样的语义存在了相当长的时间。当然,它可以通过类外初始化的形式
const std::string A::test = "42";
来工作。我猜,如果你可以把它变成非静态的,那么问题就出在其中之一。在类外范围进行初始化(通常
const
是在对象实例化时创建的)。但是,如果您正在创建与类的任何其他成员无关的对象,则我不认为这是问题。第二个问题是静态成员有多个定义。例如,如果它包含在几个.cpp
文件中,落入几个对象文件中,那么链接器在将这些对象链接在一起(例如链接到一个可执行文件)时会遇到问题,因为它们将包含相同符号的副本。据我所知,这正好等于当一个人在头文件中提供类声明下面的类外定义,然后在多个地方包含这个公共头文件时的情况。我记得,这会导致链接器错误。然而,现在处理这个问题的责任转移到用户/程序员身上。如果想要一个
static
库,需要提供一个类外定义,将其编译成单独的对象文件,然后将所有其他对象链接到这个对象文件中,因此只有一个二进制符号的定义。我阅读了Do we still need to separately define static members, even if they are initialised inside the class definition?和Why can't I initialize non-const static member or static array in class?中的答案。
我仍然想知道:
- 这只是一个标准问题,还是有更深层次的原因?
- 是否可以通过
constexpr
和用户定义的文字机制解决这个问题。clang和g++都说变量不能具有非文字类型。也许我可以创造一个。(也许由于某种原因这也是一个坏主意) - 对于链接器来说,只包含一个符号的副本真的是一个很大的问题吗?由于它是
static const
,所以所有副本应该是二进制完全相同的不可变的副本。
const
整型和枚举类型。 - juanchopanzaconst static
,真的是“multiple”吗?难道不只是副本吗?为什么不选择一个?我对连接器的内部和外部、地址转换等方面不是很熟悉。也许有人知道为什么这么困难或被弃用的想法。坦率地说,以前我认为这是与类内初始化问题有关而不是多个符号,但似乎情况并非如此。 - luk32