-2

I have the following definition of a global variable in a header that was included in several cpp file. I do have the #pragma once included.

// A.h  // only declarations and variable definition here.
#pragma once
int i = 1;
class one{public: one(); int j, p=1;};
class two{public: two(); int m, q=10;};

// B.cpp // definition of class one methods
#include "A.h"
one::one(){j=i;}

// C.cpp // definition of class two methods
#include "A.h"
two::two(){m=i;}

// D.cpp
#include "A.h"
int main()
{
 one b();
 two a();
}

when compiling the compiler returns two error that both say int i has been defined in D.obj.

  • 3
    Violates the one definition rule. `int i = 1;` is defined in places, B.cpp, C.cpp, and D.cpp since it is included in each. Headers are prepended to the file they are included in. They are not some stand alone thing that is only compiled once. – doug Mar 07 '22 at 06:36
  • @doug Thanks for the comment. Do you how to solve this? the class methods' definition require the knowledge of variable ```i ``` . ```i ``` is a global variable used across code. I have tried one way of solving it which is by turning it to a ```macro```. But are there alternative ways? – jojo_Aero_smith_the_dummy Mar 07 '22 at 06:59
  • 1
    Does this answer your question? [how to fix multiple definition error in c++?](https://stackoverflow.com/questions/35570863/how-to-fix-multiple-definition-error-in-c) – Enlico Mar 07 '22 at 07:11
  • 1
    `// A.h // only declarations and variable definition here.` Spot on, that is the problem. – Yunnosch Mar 07 '22 at 07:18
  • 1
    Use `inline` or `extern` – Sebastian Mar 07 '22 at 07:42

1 Answers1

2

Several problems in your code (some maybe be typos you made while writing the question)

  • you include headers, whereas you should #include them;
  • main has to have a return value type of int;
  • you declare classes, so without you writing public: before members, they are private by default; this results in a private constructor, for instance; you better write classes in a more readable way, by the way:
    class one {
      public:
        one();
      private:
        int j;
        int p = 1;
    };
    
  • when declaring a and b in main, you should guard against MVP; one way to do so is writing one b{}; and two a{}; instead.
  • it's good practice putting #pragma once at the top of the headers so that they don't get included more than once in each translation unit;
  • furthermore, when you define a variable in a header file, each cpp file including the header will have its own version of that variable; you need to inline those variables; from here you can read that (my emphasis)

    An inline function or inline variable (since C++17) has the following properties:

    1. ...

    2. An inline function or variable (since C++17) with external linkage (e.g. not declared static) has the following additional properties:

      1. There may be more than one definition of an inline function or variable (since C++17) in the program as long as each definition appears in a different translation unit and (for non-static inline functions and variables (since C++17)) all definitions are identical. For example, an inline function or an inline variable (since C++17) may be defined in a header file that is #include'd in multiple source files.
Enlico
  • 23,259
  • 6
  • 48
  • 102
  • yes, typos, do you have a solution for the global variable declaration of variable i? i will be used across codes. – jojo_Aero_smith_the_dummy Mar 07 '22 at 07:02
  • you might want to put `#pragma once` at the top of your header(s), to ensure they are pasted only once per translation unit. – Enlico Mar 07 '22 at 07:06
  • I do have the #pragma once included. – jojo_Aero_smith_the_dummy Mar 07 '22 at 07:07
  • @jojo_Aero_smith_the_dummy, see my edit – Enlico Mar 07 '22 at 07:23
  • 2
    @jojo_Aero_smith_the_dummy "I do have the #pragma once included." this only prevents the header from getting included as a result of other headers that might also include the header in the same cpp file. It has nothing to do with the problem here as the header is clearly included once in each of the cpp files. It's good practice because it can be hard to track down multiple inclusions. Header guards are traditionally used since they don't require recognition of the pragma. – doug Mar 07 '22 at 21:48
  • It is a pragma, where it will be difficult to find any C++ compiler that does not support it nowadays. – Sebastian Mar 07 '22 at 23:35
  • @Enlico inline only works for function when I tried it. How would you do it for variable? – jojo_Aero_smith_the_dummy Mar 08 '22 at 00:54
  • @jojo_Aero_smith_the_dummy activate C++17 or C++20 as mentioned in Enlico's answer – Sebastian Mar 08 '22 at 01:07
  • @Sebastian unfortunately I only have c++11. But I will work with extern. – jojo_Aero_smith_the_dummy Mar 08 '22 at 01:09
  • 1
    @jojo_Aero_smith_the_dummy, wow man. A question with so many typos and no useful tag. I hope you'll do a better job next time. – Enlico Mar 08 '22 at 05:50