네임스페이스(namespace)는 C++에서 식별자들을 그룹화하고 충돌을 방지하기 위한 방법으로 사용된다. 이게 무슨 말이냐면 예를 들어 A고등학교에 1학년 2반에 김민수라는 학생이 있고, 1학년 5반에 김민수라는 학생이 있어서 총 2명의 김민수가 있다면 김민수라는 학생을 부르기 위해서 이름을 부른다면 2명의 김민수가 모두 대답할 것이다. 1학년 2반의 김민수만을 부르고 싶다면 "1학년 2반 김민수"라고 부르면 1학년 2반의 김민수만 대답을 할 것이다. 이와 같은 개념이 네임스페이스다. 이 내용을 코드로 살펴보면.
#include <iostream>
namespace one_two_class_minsoo
{
void minsoo(void);
}
namespace one_five_class_minsoo
{
void minsoo(void);
}
void one_two_class_minsoo::minsoo(void)
{
std::cout<<"나는 1학년 2반 김민수야"<<std::endl;
}
void one_five_class_minsoo::minsoo(void)
{
std::cout<<"나는 1학년 5반 김민수야"<<std::endl;
}
int main(void)
{
one_two_calss_minsoo::minsoo();
one_five_calss_minsoo::minsoo();
return 0;
}
위코드를 살펴보면 one_two_calss_minsoo라는 네임스페이스와 one_five_class_minsoo라는 네임스페이스를 만들고 그 안에 공통되는 void minsoo(void) 함수를 만들었다. 이렇게 네임스페이스로 구분되면 동일한 함수 이름을 사용하더라도 충돌이 발생하지 않고 구분이 가능하다.
네임스페이스의 함수 또는 변수에 접근할 때는 네임스페이스::함수명 or 변수명 이와 같이 작성해줘야 하는데 여기서 사용되는 연산자가 바로 범위지정 연산자(scope resolution operator)다.
네임스페이스는 동일한 이름으로 여러 곳에서 선언할 수 있으며, 이것은 모두 하나의 네임스페이스로 취급된다.
#include <iostream>
namespace one_two_class_minsoo
{
void minsoo(void);
}
namespace one_two_class_minsoo
{
void minsoo_number(void);
}
namespace one_five_class_minsoo
{
void minsoo(void);
}
void one_two_class_minsoo::minsoo(void)
{
std::cout<<"나는 1학년 2반 김민수야"<<std::endl;
}
void one_two_class_minsoo::minsoo_number(void)
{
std::cout<<"내 번호는 8번이야"<<std::endl;
}
void one_five_class_minsoo::minsoo(void)
{
std::cout<<"나는 1학년 5반 김민수야"<<std::endl;
}
int main(void)
{
one_two_calss_minsoo::minsoo();
one_two_calss_minsoo::minsoo_number();
one_five_calss_minsoo::minsoo();
return 0;
}
이렇게 네임스페이스 영역을 나누어 선언해도 네임스페이스의 이름이 동일하다면 이 둘은 같은 공간으로 취급된다.
네임스페이스는 중첩도 가능하다. 네임스페이스 안에 또 다른 네임스페이스를 만들고 범위지정 연산자로 접근하면 된다.
#include <iostream>
namespace one_two_class_minsoo
{
void minsoo(void);
namespace subject_score
{
void average(void);
}
}
namespace one_two_class_minsoo
{
void minsoo_number(void);
}
namespace one_five_class_minsoo::subject_score::average(void);
{
std::cout<<"내 평균은 88점이야"<<std::endl;
}
void one_two_class_minsoo::minsoo(void)
{
std::cout<<"나는 1학년 2반 김민수야"<<std::endl;
}
void one_two_class_minsoo::minsoo_number(void)
{
std::cout<<"내 번호는 8번이야"<<std::endl;
}
void one_five_class_minsoo::minsoo(void)
{
std::cout<<"나는 1학년 5반 김민수야"<<std::endl;
}
int main(void)
{
one_two_calss_minsoo::minsoo();
one_two_calss_minsoo::minsoo_number();
one_five_class_minsoo::subject_score::average();
one_five_calss_minsoo::minsoo();
return 0;
}
네임스페이스를 사용하게 되면 네임스페이스에 선언된 함수, 변수등에 접근할 때는 항상 범위지정 연산자를 통해 접근해야 한다. 이는 분명 사용자에게 번거로운 일이다. 이렇게 번거로움을 줄여주기 위해 사용되는 키워드가 바로 using이다.
using 선언을 통해서 범위지정연산자를 사용하지 않고 바로 함수나 변수를 사용할 수 있다.
#include <iostream>
namespace one_two_class_minsoo
{
void minsoo(void);
namespace subject_score
{
void average(void);
}
}
namespace one_two_class_minsoo
{
void minsoo_number(void);
}
namespace one_five_class_minsoo
{
void minsoo(void);
}
void one_two_class_minsoo::subject_score::average(void)
{
std::cout << "내 평균은 88점이야" << std::endl;
}
void one_two_class_minsoo::minsoo(void)
{
std::cout << "나는 1학년 2반 김민수야" << std::endl;
}
void one_two_class_minsoo::minsoo_number(void)
{
std::cout << "내 번호는 8번이야" << std::endl;
}
void one_five_class_minsoo::minsoo(void)
{
std::cout << "나는 1학년 5반 김민수야" << std::endl;
}
int main(void)
{
using namespace one_two_class_minsoo;
minsoo();
minsoo_number();
subject_score::average();
one_five_class_minsoo::minsoo();
return 0;
}
main 함수 안에 네임스페이스로 선언된 one_two_class_minsoo를 using 키워드를 활용해 선언해 놓으면 네임스페이스 안에 선언된 함수에 접근할 때 범위지정연산자를 사용하지 않고 바로 접근할 수 있다.
네임스페이스는 중첩이 가능하지만 삼중, 사중으로 과도하게 중첩하는 경우는 드물다. 하지만 이렇게 과도하게 중첩이 되는 경우 네임스페이스에 별도의 별칭을 지정해 사용할 수 있다.
#include <iostream>
namespace one_two_class_minsoo
{
void minsoo(void);
namespace subject_score
{
void average(void);
namespace individual_subjects
{
int math;
int korean;
}
}
}
namespace one_two_class_minsoo
{
void minsoo_number(void);
}
namespace one_five_class_minsoo
{
void minsoo(void);
}
void one_two_class_minsoo::subject_score::average(void)
{
std::cout << "내 평균은 88점이야" << std::endl;
}
void one_two_class_minsoo::minsoo(void)
{
std::cout << "나는 1학년 2반 김민수야" << std::endl;
}
void one_two_class_minsoo::minsoo_number(void)
{
std::cout << "내 번호는 8번이야" << std::endl;
}
void one_five_class_minsoo::minsoo(void)
{
std::cout << "나는 1학년 5반 김민수야" << std::endl;
}
int main(void)
{
using namespace one_two_class_minsoo;
namespace math_score = one_two_class_minsoo::subject_score::individual_subjects;
math_score::math = 95;
minsoo();
minsoo_number();
subject_score::average();
one_five_class_minsoo::minsoo();
std::cout << "1학년 2반 민수의 수학 점수는 " << math_score::math << "점이다." << std::endl;
return 0;
}
범위지정 연사자에는 또 다른 기능이 있다. 같은 이름의 지역변수와 전역변수가 있을 때 전역변수(global)는 지역변수(static)에 의해 가려지는 특징이 있다. 하지만 범위지정 연산자를 이용한다면 전역변수에 접근이 가능하다.
int variable = 10;
int main(void)
{
int variable = 20;
variable+=33; // 지역변수에 33 더함 20 + 33 = 53
::variable+=22; // 전역변수에 22 더함 10 + 22 = 42
}
- 끝 -
'Programming language > C++' 카테고리의 다른 글
[C++] new, delete, 메모리 할당, 메모리 관리 (1) | 2024.05.02 |
---|---|
[C++] 생성자(constructor), 디폴트 생성자(default constructor), 생성자? 생성자 란? 생성자 오버로딩 (0) | 2024.05.01 |
[C++] bool(boolean), C++에서 등장하는 새로운 자료형 (0) | 2024.01.17 |
[C++] inline 함수란? (0) | 2024.01.02 |
[C++] 참조자, C++참조자, C++ 참조자란? C++ Reference (0) | 2023.06.06 |