헤더에서 작동하지 않는 상수 변수
이렇게 내 헤더에 상수 변수를 정의하면 ...
extern const double PI = 3.1415926535;
extern const double PI_under_180 = 180.0f / PI;
extern const double PI_over_180 = PI/180.0f;
다음과 같은 오류가 발생합니다.
1>MyDirectX.obj : error LNK2005: "double const PI" (?PI@@3NB) already defined in main.obj
1>MyDirectX.obj : error LNK2005: "double const PI_under_180" (?PI_under_180@@3NB) already defined in main.obj
1>MyDirectX.obj : error LNK2005: "double const PI_over_180" (?PI_over_180@@3NB) already defined in main.obj
1>MyGame.obj : error LNK2005: "double const PI" (?PI@@3NB) already defined in main.obj
1>MyGame.obj : error LNK2005: "double const PI_under_180" (?PI_under_180@@3NB) already defined in main.obj
1>MyGame.obj : error LNK2005: "double const PI_over_180" (?PI_over_180@@3NB) already defined in main.obj
그러나 헤더에서 해당 상수를 제거하고 이와 같은 헤더를 포함하는 문서에 넣으면 ...
const double PI = 3.1415926535;
const double PI_under_180 = 180.0f / PI;
const double PI_over_180 = PI/180.0f;
효과가있다
누구든지 내가 뭘 잘못하고 있는지 아이디어가 있습니까?
감사
문제는 헤더 파일에서 외부 링크로 개체 를 정의 한다는 것 입니다. 예상대로 해당 헤더 파일을 여러 번역 단위에 포함하면 외부 링크가있는 동일한 개체에 대한 여러 정의를 얻을 수 있으며 이는 오류입니다.
이를 수행하는 올바른 방법은 의도에 따라 다릅니다.
헤더 파일에 정의를 넣을 수 있지만 내부 연결 이 있는지 확인하십시오 .
C에서는 명시 적
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;
C ++
static
에서는 선택 사항입니다 (C ++const
개체에는 기본적으로 내부 연결이 있기 때문에 )const double PI = 3.1415926535; const double PI_under_180 = 180.0f / PI; const double PI_over_180 = PI/180.0f;
또는 단순히 정의되지 않은 선언 을 헤더 파일에 넣고 정의 를 하나의 구현 파일에 넣을 수 있습니다.
헤더 파일 의 선언 에는 명시 적
extern
및 이니셜 라이저 가 포함 되지 않아야합니다.extern const double PI; extern const double PI_under_180; extern const double PI_over_180;
한 구현 파일의 정의는 다음과 같아야합니다.
const double PI = 3.1415926535; const double PI_under_180 = 180.0f / PI; const double PI_over_180 = PI/180.0f;
(
extern
위 선언이 동일한 번역 단위의 정의보다 선행하는 경우 정의에서 명시 적은 선택 사항입니다.)
어떤 방법을 선택할지는 의도에 따라 다릅니다.
첫 번째 방법은 각 번역 단위에서 상수의 실제 값을 볼 수 있으므로 컴파일러가 코드를보다 쉽게 최적화 할 수 있도록합니다. 그러나 동시에 개념적으로 모든 번역 단위에서 개별적이고 독립적 인 상수 객체를 얻습니다. 예를 들어 &PI
는 각 번역 단위에서 다른 주소로 평가됩니다.
두 번째 방법은 진정한 전역 상수, 즉 전체 프로그램이 공유하는 고유 한 상수 객체를 생성 합니다. 예를 들어 &PI
는 각 번역 단위에서 동일한 주소로 평가됩니다. 그러나이 경우 컴파일러는 하나의 번역 단위에서만 실제 값을 볼 수 있으므로 최적화를 방해 할 수 있습니다.
C ++ 17부터는 "두 세계의 장점"을 결합한 세 번째 옵션 인 인라인 변수가 제공 됩니다. 인라인 변수는 외부 연결이 있어도 헤더 파일에서 안전하게 정의 할 수 있습니다.
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;
이 경우 모든 변환 단위에서 이니셜 라이저 값을 볼 수있는 명명 된 상수 개체를 얻습니다. 동시에 객체에는 외부 연결이 있습니다. 즉, 전역 주소 ID가 있습니다 ( &PI
모든 변환 단위에서 동일 함).
물론, 이와 같은 것은 일부 이국적인 목적 (C ++에서 첫 번째 변형을 호출하는 대부분의 사용 사례)에만 필요할 수 있지만 기능이 있습니다.
extern
means the 'real' definition of the variable is elsewhere, and the compiler should trust that things will hook up at link time. Having the definition inline with the extern
is weird and is what's munging up your program. If you want to have them be extern
, just define them exactly once elsewhere in your program.
The extern
storage class for them is almost certainly the cause of the problem you're seeing. If you remove it, the code will probably be fine (at least in this respect).
Edit: I just noticed that you've tagged this as both C and C++. In this respect C and C++ are really quite different (but from the error messages, you're apparently compiling as C++, not C). In C++, you want to remove the extern
, because (by default) const
variables have the static
storage class. That means each source file (translation unit) will get its own "copy" of the variable, and there won't be any conflict between definitions in different files. Since you're (probably) only using the values, not treating them as variables, having multiple "copies" won't hurt anything -- none of them will be allocated storage space.
In C, extern
is rather different, and removing the extern
won't make any real difference, because they'll be extern
by default. In this case, you really need to initialize the variables in exactly one place, and declare them extern in the header. Alternatively, you can add the static
storage class that C++ will add by default when/if you remove the extern
from the header.
The problem is that you are initializing the variables in the header file; this creates a defining declaration, which is repeated in every file that includes that header,hence the multiple definition error.
You want a non-defining declaration (no initializer) in the header file, and put the defining declaration in one of the implementation files.
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.
You need to declare the contants in the header and then define them in one of your code files. If you do not declare them anywhere, then there is a linker error when it tries to tie the declaration to the actual definition. You can also get away with using #ifdef statements to have one definition within the header.
Make sure they are declared in a header that is included by everyone that needs them and make sure they are defined exactly once.
Jacob
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.
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;
in declaring global const within header causes that each compilation unit including this hader will have own definitions global definitions with the same name. Then linker does not like that.
If You really need these in header then probably You should declare them as static.
An old question, indeed, but one useful answer is missing.
It is possible to trick MSVC into accepting static constants in headers simply by wrapping those in a "dummy" class template:
template <typename Dummy = int>
struct C {
static const double Pi;
};
template <typename Dummy = int>
const double C<Dummy>::Pi = 3.14159;
Now, C<>::PI can be accessed from elsewhere. No redefinition complains; constant is directly accessible in each compilation units without fancy link time optimization. Macro can be rolled out to further prettify this approach (even though macros are evil).
ReferenceURL : https://stackoverflow.com/questions/2328671/constant-variables-not-working-in-header
'Development Tip' 카테고리의 다른 글
인스턴스화 된 개체에 메서드 추가 (0) | 2021.01.05 |
---|---|
결과가 반환되지 않을 때 ExecuteScalar () 처리 (0) | 2021.01.05 |
PostgreSQL에서 dblink를 사용 (설치)하는 방법은 무엇입니까? (0) | 2021.01.05 |
PHP는 배열의 마지막 3 개 요소를 가져옵니다. (0) | 2021.01.05 |
iOS에서 비행기 모드 감지 (0) | 2020.12.31 |