도순씨의 코딩일지
C++ :: 이름공간(namespace) 본문
이미 언어를 여러 개 익힌 뒤라 그런지 모르겠지만 대충 내용을 훑어보면 어떤 내용일지 예상이 간다. 그런데 이번에 살펴본 이름공간은 (나에게는) 너무나도 생소한 개념이었다.
이름공간은 이름의 충돌을 막기 위한 것이다. 다음 코드를 통해서 살펴보도록 하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include <iostream>
void SimpleFunc(void){
std::cout<<"BestCom이 정의한 함수"<<std::endl;
}
void SimpleFunc(void){
std::cout<<"ProgCom이 정의한 함수"<<std::endl;
}
int main(void){
SimpleFunc();
return 0;
}
|
cs |
이 코드는 애초에 바르지 않은 코드라는 것을 눈치챌 수 있다. 똑같은 이름, 똑같은 매개변수이므로 함수 오버로딩에도 해당되지 않는다(cf. 함수 오버로딩은 똑같은 이름, 다른 매개변수) 컴파일러에서도 빨간 줄로 이 코드가 틀렸음을 알려줄 것이다.
하지만 이름공간을 사용하면 이런 문제를 해결할 수 있다.
@ 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#include <iostream>
namespace BestComImpl{
void SimpleFunc(void){
std::cout<<"BestCom이 정의한 함수"<<std::endl;
}
}
namespace ProgComImpl{
void SimpleFunc(void){
std::cout<<"ProgCom이 정의한 함수"<<std::endl;
}
}
int main(void){
BestComImpl::SimpleFunc();
ProgComImpl::SimpleFunc();
return 0;
}
|
cs |
@ 실행 결과
1
2
|
BestCom이 정의한 함수
ProgCom이 정의한 함수
|
cs |
이름 공간을 먼저 선언하고 그 안에서 함수를 선언해주었다.
C++에서 :: 는 범위 지정 연산자이다. 위의 코드에서 BestComImpl::SimpleFunc()을 예시로 들면 BestComImpl이라는 이름 공간으로 범위를 지정해주고 그 안에 SimpleFunc() 함수를 실행하도록 하는 것이다.
함수의 선언과 정의를 구분하고자 한다면 다음과 같이 표시할 수 있다.
@ 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#include <iostream>
namespace BestComImpl{
void SimpleFunc(void);
}
namespace ProgComImpl{
void SimpleFunc(void);
}
int main(void){
BestComImpl::SimpleFunc();
ProgComImpl::SimpleFunc();
return 0;
}
void BestComImpl::SimpleFunc(void){
std::cout<<"BestCom이 정의한 함수"<<std::endl;
}
void ProgComImpl::SimpleFunc(void){
std::cout<<"ProgCom이 정의한 함수"<<std::endl;
}
|
cs |
@ 실행 결과
1
2
|
BestCom이 정의한 함수
ProgCom이 정의한 함수
|
cs |
참고로 동일한 이름공간에 정의된 함수를 호출할 때는 이름 공간을 명시할 필요가 없다. 단, 다른 이름 공간에 정의된 함수를 호출할 때는 이름공간을 꼭 작성해주어야 한다. 이름 공간의 중첩 또한 가능하다.
그렇다면 우리가 습관적으로 사용해왔던 std::cout, std::cin, std::endl은 무슨 의미를 담고 있을까? std라는 이름 공간에 선언된 cout, std에 선언된 cin, std에 선언된 endl이다. 헤더파일 <iostream>의 이름공간 std안에 cout, cin, endl이 선언되어 있는 것이다.
하지만 이름공간을 계속 선언하는 것은 불편하다. 다음의 코드를 통해 이 불편함을 해결해보도록 하자.
@ 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include <iostream>
namespace Hybrid{
void HybFunc(void){
std::cout<<"So simple function!"<<std::endl;
std::cout<<"In namespace Hybrid!"<<std::endl;
}
}
int main(void){
using Hybrid::HybFunc;
HybFunc();
return 0;
}
|
cs |
@ 실행 결과
1
2
|
So simple function!
In namespace Hybrid!
|
cs |
using Hybrid::HybFunc 은 이름 공간 Hybrid에서 HybFunc을 찾으라는 의미와 같다. HybFunc은 항상 함수의 이름이여야 하는 것이 아니다. 변수의 이름이 될 수도 있다. 또한 지역 변수의 선언 개념과 비슷하게 선언된 지역을 벗어나면 효력을 잃게 된다.
using namespace std를 선언할 수도 있다.
@ 코드
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <iostream>
using namespace std;
int main(void){
int num = 20;
cout<<"Hello World!"<<endl;
cout<<"Hello "<<"World!"<<endl;
cout<<num<<' ' <<'A';
cout<<' '<<3.14<<endl;
return 0;
}
|
cs |
@ 실행 결과
1
2
3
|
Hello World!
Hello World!
20 A 3.14
|
cs |
이러한 방법이 편리해보이긴 하지만 이름 충돌을 발생할 가능성이 있으므로 적절하게 사용하는 자세가 필요하다.
앞에서 범위지정 연산자 :: 을 살펴보았다. 범위지정 연산자는 또 다른 기능이 있다. 바로 지역 변수 안에서 전역 변수를 가리키는 역할이다.
'𝐏𝐑𝐎𝐆𝐑𝐀𝐌𝐌𝐈𝐍𝐆 > 𝐂++' 카테고리의 다른 글
C++ :: 캡슐화(Encapsulation) (0) | 2020.08.14 |
---|---|
C++:: 정보은닉(Information Hiding) (0) | 2020.08.14 |
C++ :: C++에서의 파일분할 (0) | 2020.08.13 |
C++ :: 함수 오버로딩(Function Overloading) & 매개변수의 디폴트값(Default Value) (0) | 2020.07.22 |
C++ :: 입출력 방식 (0) | 2020.07.21 |