我可以在类头文件中定义一个类的const静态实例吗
Can I define a const static instance of a class in the class header file
是否可以在类头文件中声明和定义类的const静态实例。
我想做这样的事情(从这个类似的问题):
class PlaceID {
public:
inline PlaceID(const std::string placeName):mPlaceName(placeName) {}
const static PlaceID OUTSIDE;
private:
std::string mPlaceName;
};
const PlaceID PlaceID::OUTSIDE = PlaceID("");
如果PlaceID::OUTSIDE的定义在源文件中,这将起作用,但如果它在包含在多个位置的头文件中,则会导致链接错误,因为PlaceID::UTSIDE随后被定义了多次。
出于两个原因,我想在头文件中定义它。首先,这将是一个库的一部分,我希望这个库只是头文件。
第二,这是我希望编译器能够"内联"这个实例的使用的最重要的一个。有问题的类(不是这里用作示例的类)是基元类型的包装器,所有方法都内联,以便提供与基元类型相同的性能。如果我把这个实例的定义放在源文件中,编译器在编译时将不知道它的值,也无法应用一些优化。
谢谢。
在C++17中,变量可以标记为inline
:
class PlaceID
{
inline const static PlaceID OUTSIDE{""};
// ...
};
在C++14之前,您可以使用一个函数:
class PlaceID
{
static PlaceID OUTSIDE() { return PlaceID{""}; }
// ...
};
或
class PlaceID
{
static PlaceID OUTSIDE()
{
static PlaceID result{""};
return result;
}
// ...
};
取决于是否需要单个PlaceID
实例。
或者,您可以在伪参数上模板化PlaceID
,以便在标头中内联OUTSIDE
的定义:
template <typename>
struct PlaceID_
{
inline PlaceID_(const char*) { }
const static PlaceID_ OUTSIDE;
};
template <typename T>
const PlaceID_<T> PlaceID_<T>::OUTSIDE{""};
using PlaceID = PlaceID_<void>;
这是因为模板是隐式inline
。请参阅内联变量如何工作?了解更多详细信息。
wandbox.org上的实时示例
如果可能的话,还可以考虑将PlaceID::PlaceID(const char*)
标记为constexpr
,这样OUTSIDE
也可以标记为constexpr
。显然,如果您决定使用std::string
,这将不起作用。
您可以通过此(许多库常用)阻止您的头被多次包含(并导致您的问题(免责声明:我没有测试过它。)
a.hpp
#ifndef LIBRARY_A
#define LIBRARY_A
//define other things
#endif
将LIBRARY_A
替换为您选择的ID(请注意,它不会与其他库冲突,因此避免使用SOUND_SYSTEM
之类的名称,而是使用SOUND_LIBRARY_FOO
,FOO
替换为您的项目名称/您的姓名)