삶의 공유

[C++]namespace(이름 공간) 본문

Programing/C++

[C++]namespace(이름 공간)

dkrehd 2020. 10. 21. 21:58
728x90
반응형

# 출저 : 열혈 C++프로그래밍(책)

 

작은 프로젝트면 상관없지만 프로젝트가 커지게 되면 많은 함수를 써야되는 상황이 발생한다. 그렇게 되면 1개의 팀에서 혹은 1개의 회사가 아닌 여러 팀, 회사에서 프로젝트를 진행할 경우 문제가 발생할 수 있다.

바로 함수의 이름이 충돌이 나는 경우다. 

 

namespace의 정의

 

즉 이를 방지하기 위한 방법으로 namespace가 필요한 것이다.

기본원리를 설명하면, 한집에 철수라는 이름의 사람이 2명 산다면, 상황에 따라 문제가 될수 있지만, 서로 살고 있는 집이 다르다면 문제 될 것이 없다.

'201호 사는 철수', '202호 사는 철수'로 구분을 할 수 있기 때문이다. 

'201호', '202호' 와 같이 공간을 나누는 것이 namespace의 기본 원리 인 것 이다.

 

코드로 간략하게 구현하면,

#include <iostream>

namespace BestCompany1
{
    void SimpleFunc(void)
    {
        std::cout << "BestCompany1이 정의한 함수" << std::endl;
    }
}
namespace BestCompany2
{
    void SimpleFunc(void)
    {
        std::cout << "BestCompany2이 정의한 함수" << std::endl;
    }
}

int main(void)
{
	//namespace로 구분했기 떄문에 서로 동일한 함수명을 써도 상관 없다
    BestCompany1::SimpleFunc(); // :: 범위 지정 연산자(scope resolution operator)로 이름 공간을 지정할때 사용하는 연산자.
    BestCompany2::SimpleFunc();
}

 

namespace의 몇가지 특징을 살펴보면,

1) 함수 선언과 정의를 구분할 수가 있다.

#incldue <iostream>

// 선언
namespace BestCompany1
{
	void SimpleFunc(void);
}
namespace BestCompany1 // 동일한 이름 공간을 나눠서 선언했지만, 두 함수는 같은 이름 공간안에 있다 
{
	void PrettyFunc(void);
}

namespace BestCompany2
{
	void SimpleFunc(void);
}

int main(void)
{
	BestCompany1::SimpleFunc(void);
}

//정의
void BestCompany1::SimpleFunc(void)
{
	std::cout << "BestCompany1이 정의한 함수" << std::endl;
    PrettyFunc(); // 동일한 이름 공간이기때문에, :: 연산자를 별도로 쓸필요가 없다.
    BestCompany2::SimpleFunc(); // 다른 이름 공간이기 떄문에 ::를 써서 함수를 호출 해야 한다.
}
void BestCompany1::SimpleFunc(void)
{
	std::cout << "So Pretty!!!" << std::endl;
}
void BestCompany2::SimpleFunc(void)
{
	std::cout << "BestCompany2이 정의한 함수" << std::endl;
}

2. 이름 공간의 중첩을 할 수 있다.

#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; //2
	std::cout <<< Parent::SubOne::num << std::endl; //3
	std::cout <<< Parent::SubTwo::num << std::endl; //4
}

총 3개의 num이 존재하는데, 각각 선언된 이름 공간이 다르기 때문에 이름 충돌 문제가 발생하지 않는다.

 

여기서 std::cout 부분을 볼수 있는데 이것을 다른 말로하면 이름 공간 std에 선언된 cout 이라고 할 수 있다. 매번 std::를 붙이기는 너무 귀찮은 일이다 이를 해결 하기 위해 using을 이용하여 이름 공간을 명시함으로써 선언한 이후에는 이름공간을 별도로 쓰지 않아도 된다.

코드로 설명하면

1) 필요한 함수를 이렇게 하나씩 선언하는 방법과

using std::cout; 

using std::endl; 

cout << Parent::num << endl;

2) 1은 하나씩 선언하는게 귀찮기 때문에 이름 공간 std에 선언된 모든것에 대해 이름 공간 지정의 생략으로 선언하는 방법이 있다.

using namespace std;

cout << Parent::num << endl;

 

2번이 편해 보일 수 있지만, 이렇게 선언해버리면 그만큼 이름 충돌이 발생할 확률은 상대적으로 높아진다는 것을 알아야한다.

상황을 판단해서 1,2번을 적절히 혼용하는 지혜가 필요하다.

 

이름 공간 별칭

namespace AAA
{
	namespace BBB
	{
		namespace CCC
		{
			int num1;
			int num2;
		}
	}
}

이와 같이 여러 네임스페이스 공간안에 있을 경우 num1, num2을 접근하기 위해서는 

AAA::BBB::CCC::num1 = 20;

AAA::BBB::CCC::num2 = 30;

이와 같이 접근 해야한다.  매우 불편하다.

 

이를 좀 더 편리하게 하기 위해서 AAA::BBB::CCC와 같은 이름에 별칭을 줄 수 있다.

namespace ABC = AAA::BBB::CCC;

 

이렇게 하면

ABC::num1 = 20;

ABC::num2 = 30;

으로 접근 할 수 있다.

 

마지막으로 범위 지정 연산자의 또다른 기능을 살펴보면

지역 변수의 이름이 전역변수의 이름과 같을 경우, 전역 변수는 지역변수에 의해 가려지는 특징이 있는데 이것을 범위 지정 연산자를 통해서 전역변수를 선택 할 수가 있다.

 

int val = 100; // 전역변수

int SimpleFunc(void)
{
   int val = 20; // 지역변수
   val += 3; // 23 (지역변수 val의 값 3 증가)
}

// 범위 지정 연산자를 사용하면,

int val = 100; // 전역변수

int SimpleFunc(void)
{
   int val = 20; // 지역변수
   val += 3; // 23 (지역변수 val의 값 3 증가)
   ::val += 7 // 107(전역변수 val의 값 7 증가)
}

 

반응형

'Programing > C++' 카테고리의 다른 글

[C++] 코딩테스트 준비(백준, 고양이문제)  (0) 2021.01.14
[C++] Call by reference & Call by Value  (0) 2020.11.09
[C++]참조자(Reference) 정의  (0) 2020.11.02
C++ 자료형 bool  (0) 2020.10.26
[C++]인라인(Inline) 함수  (0) 2020.10.21