此问题已在此处有答案:
How can you define a static data member of type const std::string?(11个回答)
How to initialize private static data members in a header file(18个回答)
8天前关闭
Given是一个具有静态成员的类。
class BaseClass
{
public:
static std::string bstring;
};
显然,String必须在类外部进行 default-initialized。
std::string BaseClass::bstring {"."};
如果我将上面的行与类一起沿着包含在标题中,我会得到一个symbol multiply defined
错误。它必须在单独的cpp
文件中定义,即使是include guards
或pragma once
。
有没有办法在header中定义它?
7条答案
按热度按时间kh212irz1#
不能多次定义
static
成员变量。如果你把变量定义放在一个头文件中,它将在包含头文件的每个翻译单元中定义。由于包含守卫只影响一个翻译单元的编译,它们也不会有帮助。但是,您可以定义
static
成员函数!现在,乍一看,它可能没有帮助,当然,该函数可以有本地static
变量,并返回对其中一个的引用,其行为几乎像static
成员变量:本地变量
static
将在第一次调用此函数时初始化。也就是说,构造被延迟到第一次访问函数。当然,如果你使用这个函数初始化其他全局对象,它也可以确保对象是及时构造的。如果你使用多线程,这可能看起来像一个潜在的数据竞争,但它不是(除非你使用C++03):函数localstatic
变量的初始化是线程安全的。ujv3wf0j2#
在C++17中,你可以使用 inline variables,甚至可以在 outside classes中使用。
声明为constexpr的静态成员变量(但不是命名空间作用域变量)隐式地是内联变量。
举例来说:
或者
联系我们
cwdobuhd3#
关于
**"**有没有办法在header中定义[static data member]?
是的。
另一种方法是使用函数,正如Dietmar建议的那样。本质上,这是一个迈耶斯的单身(谷歌它)。
无论如何,三思而后行关于这里的设计。全局变量是Evil™。这基本上是全球性的。
42fyovps4#
在C++11中,为了保持静态值的定义与声明,可以使用嵌套的静态结构。在这种情况下,静态成员是一个结构,必须在.cpp文件中定义,但值在头文件中。
不是初始化单个成员,而是初始化整个静态结构:
这些值是通过
请注意,该解决方案仍然存在静态变量初始化顺序的问题。当一个静态值被用来初始化另一个静态变量时,第一个变量可能还没有被初始化。
在这种情况下,静态变量 headers 将包含{“”}或{“.h”,“.hpp”},这取决于链接器创建的初始化顺序。
2skhul335#
§3.2.6
和来自当前c++ 17草案(n4296)的以下段落定义了在不同的翻译单元中可以存在多个定义时的规则:一个类类型(第9章)、枚举类型(第7.2章)、具有外部链接的内联函数(第7.1.2章)、类模板(第14章)、非静态函数模板(第14.5.6章)、类模板的静态数据成员(第14.5.1.3章)、类模板的成员函数(第14.5.1.1章)或在程序中未指定某些模板参数的模板专用化(第14.7章、第14.5.5章)的定义可以不止一个,只要每个定义出现在不同的翻译单元中,并且定义满足以下要求。给定这样一个名为D的实体定义在多个翻译单元中,那么[...]
显然,类类型的静态数据成员的定义不被认为出现在多个翻译单元中。因此,* 根据标准,这是不允许的 *。
来自Cheers和hth的建议答案。- Alf和Dietmar更像是一种“黑客”,利用了
类模板的静态数据成员(14.5.1.3)
和
带外部链接的内联函数(7.1.2)
允许在多个TU中使用(仅供参考:在类定义内部定义的静态函数具有外部链接,并且被隐式地定义为内联)。
vsaztqbk6#
不,它不能在头文件中完成-至少如果头文件不止一次包含在源文件中,这似乎是事实,否则你不会得到这样的错误。只要把它放在一个.cpp文件中就可以了。
mftmpeh87#
更新:我下面的回答解释了为什么这不能以问题所建议的方式完成。至少有两个答案可以回避这一点;他们可能会解决问题,也可能不会。
bstring
静态成员必须链接到特定的内存地址。要做到这一点,它必须出现在单个对象文件中,因此它必须出现在单个cpp
文件中。除非你使用#ifdef
来确保这一点,否则你想要的东西不能在头文件中完成,因为你的头文件可能包含在多个cpp
文件中。