0
class TestClass
{
public:
    static int testMember;

    template<class T> static  T* Foo()
    {
        //Defination....
    }
}
//int TestClass::testMember;  //Duplicate definition

Why can't I define a member field in .hpp while I can define member functions in .hpp?

Does it must be defined in a .cpp file?

user438383
  • 5,716
  • 8
  • 28
  • 43
Creedon
  • 21
  • 1
  • Please take the [tour], and inform yourself at the [help] what and how you can ask here. – πάντα ῥεῖ Dec 05 '21 at 18:06
  • 2
    A header file is just source code. If you have the definition in the header file, then you can only have one *translation unit* use that header file. But that rather defeats the purpose of the header file as being a place to *declare* things so they can be referred to across translation units, rather than to *define* things. – Eljay Dec 05 '21 at 18:06
  • 2
    You can, you just need to add `inline` keyword. – Igor Tandetnik Dec 05 '21 at 18:08
  • @Eljay is right: An `#include` preprocessor directive is simply replaced by the header file's text. Whether the definition is in a header file or directly written in the cpp file is irrelevant: If it occurs more than once (after the header file has been inserted) the one definition rule is violated. And Igor is right, too, with modern C++17 . – Peter - Reinstate Monica Dec 05 '21 at 18:13
  • A non-`inline` static member must be defined exactly once in the whole program. If the header file is included by more than once source file, that static variable will be defined once for every source file that includes it. The two simple ways of avoiding this are to avoid defining a non-`inline` static data member in a header, or mark it `inline` (in which case, the compiler or linker typically sorts out the fact that the definition is seen by multiple source files). – Peter Dec 05 '21 at 18:41

2 Answers2

3

Why can't I define a member field in .hpp

You can.

C++ doesn't care what you name your files, and doesn't care what extension the files have.

What you can't do is define the variable more than once. That would obviously violate the one definition rule.

In order to satisfy the one definition rule, you have two options:

  • In C++17 or later, make the variable inline.

    class TestClass
    {
    public:
      static inline int testMember;
    
      template<class T> static  T* Foo()
      {
          //Defination....
      }
    }
    
  • In any version of C++, place the definition in your code where it will be compiled exactly once.

Why ... [can I] define member functions in .hpp?

Because member functions, defined in the class, are implicitly inline. Just like your variable could be.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • Thanks for your answer. I used to regard .hpp as a special compile unit that can be included.because many template libs use it to define functions without 'inline'. – Creedon Dec 06 '21 at 04:31
1

As Drew Dormann has mentioned, template member functions (static or not) are implicitly inline.
The same goes for class templates:

template <typename>
class TestClass
{
public:
    static int testMember;

    template<class T> static  T* Foo()
    {
        //Definition....
    }
};

// prior to C++17 you definition MUST be outside the class in the header
template <typename T>
int TestClass<T>::testMember{};
Sergey Kolesnik
  • 3,009
  • 1
  • 8
  • 28
  • 1
    Um, in the question, `TestClass` is not a template. Why did it become one here? – Pete Becker Dec 05 '21 at 20:06
  • @PeteBecker the OP apparantelly wants his static member to be defined within the header file. And this answer is an extension to existing one. It just shows that like a template member function can be inlined a class template also can be. So this is an example of a code with a static member **defined** within a .hpp file. Why so agitated though? – Sergey Kolesnik Dec 05 '21 at 20:21