Multiple including a head file with a variable definition

后端 未结 4 675
野趣味
野趣味 2021-01-28 00:03

I just build a simple C++ project. The codes are shown in the follows:

-------- head.h --------

#ifndef _HEAD_H_
#define _HEAD_H_

int my_var = 100;

#en         


        
相关标签:
4条回答
  • 2021-01-28 00:44

    Change the header the following way

    #ifndef _HEAD_H_
    #define _HEAD_H_
    
    extern int my_var;
    
    #endif
    

    And for example add line in the module with main

    #include "head.h"
    int my_var = 100;
    int main() { return 0; }
    

    The problem is that as the header is included in two modules then each module contains a variable with external linkage with the same name as a variable in other module. And the linker does not know which variable to use.

    0 讨论(0)
  • 2021-01-28 00:52

    The guard only prevents the header from being included twice in the same compilation unit.

    When you compile src1.o and src2.o, each one will contain a definition of my_var. When you link them to create a.out, the compiler cannot merge those definitions (even if they are identicals), and fails.

    What you want to do is declare my_var as extern :

    ---- head.h ----

    #ifndef _HEAD_H_
    #define _HEAD_H_
    
    extern int my_var;
    
    #endif
    

    ---- my_var.c ----

    #include "head.h"
    
    int my_var = 100;
    

    Then compile all source files :

    g++ -c my_var.cpp -o my_var.o
    g++ -c src1.cpp -o scr1.o
    g++ -c src2.cpp -o src2.o
    g++ -o a.out my_var.o src2.o src1.o
    

    This way, my_var will be declared in every file, but will only be defined in my_var.o. There is an important difference here. Try to omit linking my_var.o, you'll see what the compiler has to say :)

    0 讨论(0)
  • 2021-01-28 00:55

    You are defining my_var once per compilation unit. Remember that include guards operate on a per compilation unit basis.

    To remedy, you should declare my_var as extern in the header:

    #ifndef _HEAD_H_
    #define _HEAD_H_
    
    extern int my_var;
    
    #endif
    

    and define it in one of the source files using

    int my_var = 100;
    

    Then the linker sees only one definition and all will be fine.

    0 讨论(0)
  • 2021-01-28 01:08

    your problem boils down to understanding C++ storage classes; static and extern more precisely.

    extern says: this variable is defined in a different file, this 
                 is only a declaration
    static says: this variable's lifetime is the program lifetime and
                 restrict it's visibility to the current file. 
    
    
    
    What happens in your case:
       - each file includes the variable declaration and definition `int my_var = 100;`,
         so both object scr1.o and scr2.o will contain the variable definition. When
         linking them, the linker cannot solve the ambiguity and throws an error.
       - adding the extern qualifier and defining the variable in one of the files 
         solves this problem: in one source it'll be an external unresolved at compile
         time, symbol and the other will contain the actual symbol.
    

    As for the second part of your question; why adding static seems to help the linker. Look at what I just said about static storage class: basically each object will have their own copy of the variable - not the same one!

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