‘이름공간’이란 특정 영역에 이름을 붙여주기 위한 문법적 요소이다.
이름공간의 등장 배경
여러 명이서 협업을 하는 규모가 큰 프로젝트가 있다고 가정하자. 만약 불운하게 개발자들이 만든 함수들의 이름이 서로 같다면 컴파일 에러가 날 것이다. 서로 같은 이름을 가진 함수라도 서로 다른 영역에 있음을 규정할 수 있다면 컴파일 에러를 막을 수 있을 것이다. 이러한 전제 하에 이름공간의 개념이 등장하게 되었다.
이름공간은 아래 예제와 같이 사용될 수 있다.
#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;
}
함수를 호출할 때 범위지정 연산자 ::을 사용해 어느 이름공간의 함수를 호출하는지 정의할 수 있다.
이름공간은 다음과 같은 특징을 지닌다.
- 이름공간에 속한 함수의 원형을 선언할 때는 아래와 같은 형식을 취한다.
#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;
}
- 동일한 이름공간에 정의된 함수를 호출할 때는 이름공간을 명시할 필요가 없다.
#include <iostream>
namespace BestComImpl
{
void SimpleFunc(void);
}
namespace BestComImpl
{
void PrettyFunc(void);
}
namespace ProgComImpl
{
void SimpleFunc(void);
}
int main(void)
{
BestComImpl::SimpleFunc();
return 0;
}
void BestComImpl::SimpleFunc(void)
{
std::cout<<"BestCom이 정의한 함수"<<std::endl;
PrettyFunc(); //동일한 이름공간의 함수를 호출할 떄는 범위 지정 연산자가 불필요
ProgComImpl::SimpleFunc();
}
void BestComImpl::PrettyFunc(void)
{
std::cout<<"So Pretty!!"<<std::endl;
}
void ProgComImpl::SimpleFunc(void)
{
std::cout<<"ProgCom이 정의한 함수"<<std::endl;
}
- 이름공간은 다른 이름공간 안에 삽입될 수 있다. 이러한 특성을 이름공간의 중첩이라 한다.
#include <iostream>
namespace Parent
{
int num=2;
namespace SubOne //이름 공간의 중첩
{
int num=3;
}
namespace SubTwo
{
int num=4;
}
}
int main(void)
{
//아래와 같은 형태로 호출한다.
std::cout<<Parent::num<<std::endl;
std::cout<<Parent::SubOne::num<<std::endl;
std::cout<<Parent::SubTwo::num<<std::endl;
}
- 이름공간이 과다하게 중첩되었을 때 별칭을 지정하여 코드를 축약할 수 있다.
#include <iostream>
using namespace std;
namespace AAA
{
namespace BBB
{
namespace CCC
{
int num1;
int num2;
}
}
}
int main(void)
{
AAA::BBB::CCC::num1=20;
AAA::BBB::CCC::num2=30;
namespace ABC=AAA::BBB::CCC; //이와 같은 형식으로 축약할 수 있다.
cout<<ABC::num1<<endl;
cout<<ABC::num2<<endl;
return 0;
}
- using 키워드를 사용하면 범위지정 연산자를 생략할 수 있다. 함수 안에서 사용된 using 키워드는 지역변수와 같이 함수 안에서만 효력을 가진다. 프로그램 전체에 영향을 끼치려면 전역변수와 마찬가지로 함수 밖에 선언을 해야 한다. using 키워드를 namespace 전체에 적용하면 해당 namespace의 요소 모두를 범위지정 연산자를 생략하여 사용할 수 있다. 하지만 이름충돌의 위험이 증가함으로 상황을 고려해 알맞게 사용해야 한다.
#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(); //using 키워드가 선언된 함수에 한하여 ::생략
return 0;
}
#include <iostream>
using std::cin; //프로그램 전체에 using 키워드 적용
using std::cout;
using std::endl;
int main(void)
{
int num=20;
cout<<"Hello World!"<<endl;
cout<<"Hello "<<"World!"<<endl;
cout<<num<<' '<<'A';
cout<<' '<<3.14<<endl;
return 0;
}
#include <iostream>
using namespace std; //using 키워드를 이름공간 전체에 적용
int main(void)
{
int num=20;
cout<<"Hello World!"<<endl;
cout<<"Hello "<<"World!"<<endl;
cout<<num<<' '<<'A';
cout<<' '<<3.14<<endl;
return 0;
}
참고자료