하나의 정의 규칙을 구현하는 방법
-
22-08-2019 - |
문제
이 게시물 하나의 정의 규칙에 대한 참조.
Wikipedia는 그것을 구현하는 방법을 설명하는 데 꽤 나쁘다
C ++ .NET에서 따라야 할 지침에 대한 좋은 resSources는 어디에서 찾을 수 있습니까?
해결책
하나의 정의 규칙은 기본적으로 변수/함수가 컴파일 된 실행 파일의 주소 공간의 한 곳에만 위치 할 수 있음을 의미합니다. 그것을 생각하는 한 가지 방법은 컴파일하는 동안 컴파일 된 프로그램 (객체 코드)에서 사용할 메모리 배열과 변수/함수 위치를 참조하기위한 조회 테이블이 있습니다. 이것은 프로세스 당 수준에서 수행됩니다. 다음이 간단한 프로그램이라고 가정합니다.
파일 1.cpp
int square(int x); // this is a declaration
extern int someVariable; // this is a declration
void square(int x) // this is a definition
{
return x * someVariable;
}
file2.cpp
int square(int x); // this is a declaration
int someVariable; // this is a definition
void main()
{
someVariable = 12;
someVariable = square(4);
}
컴파일러가 객체 코드를 컴파일하기 시작하면 선언을 읽고 테이블에 넣습니다. File 1.cpp를 컴파일하면 다음과 같은 것이 있습니다.
declarations:
square (XX): function that returns int, and takes a single int as parameter [4 bytes]
someVariable (YY): integer [4 bytes]
data:
12 34 56 78 aa XX XX XX XX ab cd
definition:
square: starts at address 0
이는 기능이 특정 어셈블리 지침에 컴파일된다고 가정합니다. 링커 시간에 xx xx xx xx는 약간의 변환의 주소로 대체됩니다.
file2는 다음과 같은 것입니다.
declarations:
square (XX): function that returns int, and takes a single int as parameter [4 bytes]
someVariable (YY): integer [4 bytes]
data:
00 00 00 00 12 34 56 78 12 34 56 YY YY YY YY 23 21
definitions:
someVariable: starts at address 0
main: starts at address 4
이 경우 YY는 정사각형 주소로 대체됩니다.
그것이 링커가 작동하는 곳입니다. 링커의 임무는 목록을 통과하고 컴파일 타임에 프로그램의 주소 공간에있는 모든 것이 어디에 있는지 테이블을 구축하는 것입니다. 그러나 두 객체 파일이 링크를 시도 할 때 변수의 정의가 동일한 경우 문제가 있습니다. 위의 예에서 일부 변환에 대한 두 가지 정의가 있었다면 YY를 대체해야 할 사항을 알 수 없습니다. 마찬가지로, 있다면 아니요 정의, 그런 다음 추악한 링커 오류가 발생합니다.
규칙에 대한 "솔루션"은 .cpp 파일에만 정의가 있고 .h 파일에 사물의 선언이 있도록 파일을 분할하는 것입니다. 위의 예는 다음과 같습니다.
파일 1.cpp
#include "file2.h"
void square(int x) // this is a definition
{
return x * someVariable;
}
파일 1.H
int square(int x); // this is a declaration
file2.cpp
#include "file1.h"
int someVariable; // this is a definition
void main()
{
someVariable = 12;
someVariable = square(4);
}
file2.h
extern int someVariable;
이것은 엄청나게 간단한 예이며, 선언과 정의 사이의 구별 개념이 없기 때문에 .NET에는 실제로 적용되지 않습니다.
다른 팁
하나의 정의 규칙을 준수하는 가장 쉬운 방법은 정의를 헤더 대신 .CPP 파일에 넣는 것입니다.
사람들은 때때로 매크로 및/또는 전처리 조건을 사용하여 헤더에 정의를 넣어 한 편집 장치에서만 객체 또는 기능을 정의합니다. 그러나 정의를 .cpp 파일에 넣는 것이 일반적으로 (그리고 확실히 이해하기 쉬운) 더 쉽습니다.