0

Staitc member has to defined in a sourcefile(.cpp) because it will cause error due to duplicate definitions since headerfile(.h) is shared with many sourcefiles. However, if i type '#pragma once at the beginning of the heaerfile (or use #ifndef, #endif). it will only run the headerfile once. Then why we still need to initialize static member in a sourcefile?

// This is string1.h 
#pragma once
#include <cstring>                 // string.h for some


using std::ostream;
using std::istream;

static int num_strings=1; //why this still gives multiple definiton error even with #proagma once at top?
class String
{
private:
    static int num_strings; // number of objects
} 

3 Answers3

4

#pragma once does not stop a header file from being compiled multiple times.

If you have two .cpp files and each includes a header file, then that header file will be compiled twice. It cannot be any other way because C++ uses separate compilation for each .cpp file. So what happens in one compilation cannot affect what happens in another compilation.

What #pragma once does is stop a header file being compiled twice during a single compilation. So your won't get errors if you include a header twice in the same .cpp file. This happens more often than you might think. For instance a .cpp file could include two different header files, but each of those header files includes a third common header file. So indirectly the common header file is being included twice in the .cpp file. It's this problem that #pragma once is designed to fix.

Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35
john
  • 85,011
  • 4
  • 57
  • 81
2

Your line of reasoning is wrong. Header guards are to prevent including the header more than once in a single translation unit. Suppose you have two source files:

// foo.cpp
#include "theheader.h"

// bar.cpp
#include "theheader.h"
#include "someotherheader.h"

Then those two will be compiled seperately, each has the contents of the header. The header guard only prevents to include "theheader.h" twice if for example the other header is

// someotherheader.h
#include "theheader.h"

To summarize, I allow myself to steal from a comment: "Include guards avoid that file is included multiple time in same translation unit, not across several translation unit"

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
1

Since C++17 you can get around the ODR violation by making the variable inline:

static inline int num_strings=1; 
class String
{
private:
    static inline int num_strings{}; // number of objects
} 

See this for more information.

Btw, those are two distinct variables. One is num_strings and the other is String::num_strings.

Timo
  • 9,269
  • 2
  • 28
  • 58