c++ - 我可以在类头文件中定义类的 const static 实例吗

标签 c++

是否可以在类头文件中声明和定义一个类的const static实例。

我想做这样的事情(来自 this 类似的问题):

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::OUTSIDE 随后被定义了多次。

我想在头文件中定义它有两个原因。首先,这将是库的一部分,我希望该库只是头文件。

其次,这是最重要的一点,我希望允许编译器“内联”该实例的使用。所讨论的类(不是此处用作示例的类)是原始类型的包装器,所有方法都内联以提供与原始类型相同的性能。如果我将此实例的定义放在源文件中,编译器将不知道它在编译时的值,也无法应用一些优化。

谢谢。

最佳答案

在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 进行模板化,以便在 header 中内联 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>;

之所以可行,是因为模板是隐式内联。参见 How do inline variables work?了解更多详情。

live example on wandbox.org


还可以考虑将 PlaceID::PlaceID(const char*) 标记为 constexpr 如果可能,这样 OUTSIDE 可以标记为 constexpr 也是。显然,如果您决定使用 std::string,这将不起作用。

关于c++ - 我可以在类头文件中定义类的 const static 实例吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47265300/

相关文章:

c++ - boost::variant 和 STL 容器 - 我做错了吗?

c++ - std::list 可以包含不同的 std::unique_ptr<T> 吗?

c++ - 强类型能防止缓冲区溢出吗?

c++ - 基于欧拉公式的配分函数

c# - Windows Mobile - 停止主手机应用程序

使用递归的 C++ vector 元素求和

c++ - 条件变量中触发错误信号的频率如何?

c++ - 在 C++ 中将 -inf 和 inf 值过滤为 0

c++ - 从模板类继承的类的正确声明

c++ - 将 C/C++ 代码从 Linux 转移到 Windows 真的很慢