How to initialize static members in the header

前端 未结 8 1027
伪装坚强ぢ
伪装坚强ぢ 2020-12-13 09:02

Given is a class with a static member.

class BaseClass
{
public:
    static std::string bstring;
};

String has obviously to be default-

相关标签:
8条回答
  • 2020-12-13 09:06

    UPDATE: My answer below explains why this cannot be done in the way suggested by the question. There are at least two answers circumventing this; they may or may not solve the problem.


    The bstring static member has to be linked to a specific memory address. For this to happen, it has to appear in a single object file, therefore it has to appear in a single cpp file. Unless you're playing with #ifdef's to make sure this happens, what you want cannot be done in the header file, as your header file may be included by more than one cpp files.

    0 讨论(0)
  • §3.2.6 and the following paragraphs from the current c++ 17 draft (n4296) define the rules when more than one definition can be present in different translation units:

    There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then [...]

    Obviously definitions of static data members of class type are not considered to appear in multiple translations units. Thus, according to the standard, it is not allowed.

    The suggested answers from Cheers and hth. - Alf and Dietmar are more kind of a "hack", exploiting that definitions of

    static data member of a class template (14.5.1.3)

    and

    inline function with external linkage (7.1.2)

    are allowed in multiple TU ( FYI: static functions defined inside a class definition have external linkage and are implicitly defined as inline ) .

    0 讨论(0)
  • 2020-12-13 09:08

    Regarding

    Isn't there a way to define [the static data member] in the header?

    Yes there is.

    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>
    {};
    

    An alternative is to use a function, as Dietmar suggested. Essentially that is a Meyers' singleton (google it).

    Edit: Also, since this answer was posted we've got the inline object proposal, which I think is accepted for C++17.

    Anyway, think twice about the design here. Globals variables are Evil™. This is essentially a global.

    0 讨论(0)
  • 2020-12-13 09:11

    If the initializer can be expressed as a literal, it is solved in C++11:

    inline std::string operator"" _s(const char* p, size_t n) {
        return std::string{p, n};
    }
    
    class BaseClass {
        // inline initialization using user-defined literals
        // should allow for multiple definitions
        std::string bstring{"."_s};
    };
    
    0 讨论(0)
  • 2020-12-13 09:22

    In C++17 you can use inline variables, which you can use even outside classes.

    The inline specifier, when used in a decl-specifier-seq of a variable with static storage duration (static class member or namespace-scope variable), declares the variable to be an inline variable.

    A static member variable (but not a namespace-scope variable) declared constexpr is implicitly an inline variable.⁽¹⁾

    For example:

    class Someclass {
    public:
        inline static int someVar = 1;
    };
    

    Or,

    namespace SomeNamespace {
        inline static int someVar = 1;
    }
    

    ⁽¹⁾ https://en.cppreference.com/w/cpp/language/inline

    0 讨论(0)
  • 2020-12-13 09:23

    No, it can't be done in a header - at least not if the header is included more than once in your source-files, which appears to be the case, or you wouldn't get an error like that. Just stick it in one of the .cpp files and be done with it.

    0 讨论(0)
提交回复
热议问题