App*_*ell 35 c++ class static-members
给定是一个具有静态成员的类.
class BaseClass
{
public:
static std::string bstring;
};
Run Code Online (Sandbox Code Playgroud)
字符串显然是在类之外进行默认初始化.
std::string BaseClass::bstring {"."};
Run Code Online (Sandbox Code Playgroud)
如果我在标题中包含上面的行以及类,我会收到symbol multiply defined错误.它必须在单独的cpp文件中定义,即使使用include guards或pragma once.
有没有办法在标题中定义它?
Die*_*ühl 58
您不能static多次定义成员变量.如果将变量定义放入标题中,则将在包含标题的每个转换单元中定义它.由于包含警卫只影响一个翻译单元的编译,他们也无济于事.
但是,您可以定义static成员函数!现在,乍一看,它可能看起来不像它可能会有所帮助,当然,除了该函数可以有局部static变量并返回对这些行为之一的引用,就像static成员变量一样:
static std::string& bstring() { static std::string rc{"."}; return rc; }
Run Code Online (Sandbox Code Playgroud)
static第一次调用此函数时,将初始化局部变量.也就是说,构造被延迟直到第一次访问该功能.当然,如果使用此函数初始化其他全局对象,它还可以确保对象是及时构造的.如果你使用多个线程,这可能看起来像一个潜在的数据竞争,但它不是(除非你使用C++ 03):函数局部static变量的初始化是线程安全的.
And*_*and 18
在 C++17 中,您可以使用内联变量,甚至可以在类外部使用。
内联说明符在具有静态存储期的变量(静态类成员或命名空间范围变量)的声明说明符序列中使用时,将变量声明为内联变量。
声明为 constexpr 的静态成员变量(但不是命名空间范围的变量)隐式为内联变量。?¹?
例如:
class Someclass {
public:
inline static int someVar = 1;
};
Run Code Online (Sandbox Code Playgroud)
或者,
namespace SomeNamespace {
inline static int someVar = 1;
}
Run Code Online (Sandbox Code Playgroud)
?¹? https://en.cppreference.com/w/cpp/language/inline
Che*_*Alf 10
关于
"有没有办法在标题中定义[静态数据成员]?
就在这里.
template< class Dummy >
struct BaseClass_statics
{
static std::string bstring;
};
template< class Dummy >
std::string BaseClass_statics<Dummy>::bstring = ".";
class BaseClass
: public BaseClass_statics<void>
{};
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用一种功能,正如Dietmar建议的那样.基本上这是迈耶斯的单身人士(google it).
编辑:此外,由于这个答案已经发布,我们已经有了内联对象提案,我认为这个提议已被C++ 17接受.
无论如何,在这里三思而后行.Globals变量是Evil™.这基本上是一个全球性的.
为了使用 C++11 中的声明保持静态值的定义,可以使用嵌套的静态结构。在这种情况下,静态成员是一个结构,必须在 .cpp 文件中定义,但值在标题中。
class BaseClass
{
public:
static struct _Static {
std::string bstring {"."};
} global;
};
Run Code Online (Sandbox Code Playgroud)
不是初始化单个成员,而是初始化整个静态结构:
BaseClass::_Static BaseClass::global;
Run Code Online (Sandbox Code Playgroud)
这些值通过访问
BaseClass::global.bstring;
Run Code Online (Sandbox Code Playgroud)
请注意,此解决方案仍然存在静态变量初始化顺序的问题。当一个静态值被用来初始化另一个静态变量时,第一个可能还没有被初始化。
// 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 };
Run Code Online (Sandbox Code Playgroud)
在这种情况下,静态变量头将包含 { "" } 或 { ".h", ".hpp" },具体取决于链接器创建的初始化顺序。
| 归档时间: |
|
| 查看次数: |
44536 次 |
| 最近记录: |