constant variables not working in header

后端 未结 10 1955
悲&欢浪女
悲&欢浪女 2020-11-30 20:10

if I define my constant varibles in my header like this...

extern const double PI = 3.1415926535;
extern const double PI_under_180 = 180.0f / PI;
extern cons         


        
相关标签:
10条回答
  • 2020-11-30 20:32

    It looks like that header file is getting included multiple times. You need to add guards.

    At the top of each header file you should have something like:

    #ifndef MY_HEADER_FILE_NAME_H
    #define MY_HEADER_FILE_NAME_H
    
    ...
    
    // at end of file
    #endif
    

    If you are using g++ or MSVC then you can just add:

    #pragma once
    

    At the top of each header file, but that isn't 100% portable.

    Also, you shouldn't define constants in header files, only declare them:

    // In header file
    extern const int my_const;
    
    
    // In one source file
    const int my_const = 123;
    
    0 讨论(0)
  • 2020-11-30 20:44

    The problem is that you define objects with external linkage in header file. Expectedly, once you include that header file into multiple translation units, you'll get multiple definitions of the same object with external linkage, which is an error.

    The proper way to do it depends on your intent.

    1. You can put your definitions into the header file, but make sure that they have internal linkage.

      In C that would require an explicit static

      static const double PI = 3.1415926535; 
      static const double PI_under_180 = 180.0f / PI; 
      static const double PI_over_180 = PI/180.0f; 
      

      In C++ static is optional (because in C++ const objects have internal linkage by default)

      const double PI = 3.1415926535; 
      const double PI_under_180 = 180.0f / PI; 
      const double PI_over_180 = PI/180.0f; 
      
    2. Or you can put mere non-defining declarations into the header file and put the definitions into one (and only one) implementation file

      The declarations in the header file must include an explicit extern and no initializer

      extern const double PI; 
      extern const double PI_under_180; 
      extern const double PI_over_180; 
      

      and definitions in one implementation file should look as follows

      const double PI = 3.1415926535; 
      const double PI_under_180 = 180.0f / PI; 
      const double PI_over_180 = PI/180.0f; 
      

      (explicit extern in the definitions is optional, if the above declarations precede the definitions in the same translation unit).

    Which method you will choose depends on your intent.

    The first method makes it easier for the compiler to optimize the code, since it can see the actual value of the constant in each translation unit. But at the same time conceptually you get separate, independent constant objects in every translation unit. For example, &PI will evaluate to a different address in each translation unit.

    The second method creates truly global constants, i.e. unique constant objects that are shared by the entire program. For example, &PI will evaluate to the same address in each translation unit. But in this case the compiler can only see the actual values in one and only one translation unit, which might impede optimizations.


    Starting from C++17 you get the third option, which sort of combines "the best of both worlds": inline variables. Inline variables can be safely defined in header files despite having external linkage

    inline extern const double PI = 3.1415926535; 
    inline extern const double PI_under_180 = 180.0f / PI; 
    inline extern const double PI_over_180 = PI/180.0f; 
    

    In this case you get a named constant object whose initializer value is visible in all translation units. And at the same time the object has external linkage, i.e. it has a global address identity (&PI is the same in all translation units).

    Granted, something like that might only be necessary for some exotic purposes (most use cases in C++ call for the first variant), but the feature is there.

    0 讨论(0)
  • 2020-11-30 20:45

    If you want to define constants in header files, use static const. If you use extern, the linker is right to complain about multiple definitions because each including source file will supply memory for the variable if you assign a value.

    0 讨论(0)
  • 2020-11-30 20:46

    A lot of incorrect responses below. The ones that are correct are the ones telling you to remove the extern as sellibitze has also said in his comment are correct.

    Because these are declared const, there is no problem having the definition in the header. C++ will inline a const for a built in type unless you attempt to take its address (a pointer to a const) in which case it will instantiate it with static linkage, you may then also get multiple instantiations in separate modules, but unless you expect all pointers to the same const to have the same address, this is not a problem.

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