1. 이름공간(Namespace)
1.1 이름공간의 등장
여러 사람이 공동으로 모여 규모가 큰 프로그램을 개발하면 변수와 함수의 이름이 중복되는 경우가 발생한다. 예를 들어, RPG 게임을 개발하는데 두 회사가 참여했다고 생각해보자. 두 회사는 열심히 프로그램을 작성하였고, 6개월 후 각각 맡은 부분을 하나로 통합하려고 한다. 그런데 주인공의 공격 함수의 이름과 몬스터의 공격 함수의 이름이 Attack으로 우연히 같다는 것을 알게 된다. 함수의 이름이 같으니 충돌이 발생하고, 결국 프로그램에서 Attack 함수를 사용하는 부분을 전부 수정해야하는 골치 아픈 문제가 발생한 것이다. C++는 이름공간(Namespace)을 통해 이러한 문제를 근본적으로 해결할 수 있다.
1.2 이름공간의 선언과 정의
이름공간은 특정한 공간을 선언하여 그 안에 함수와 변수를 선언하는 것을 말한다. 이름공간을 만들고 그 안에 함수를 정의하거나 변수를 선언한다면 이름충돌 사고는 발생하지 않는다. 이름공간을 정의하려면 다음과 같은 형식을 따르면 되고, 이름공간에 정의한 변수와 함수는 범위 지정 연산자(::)를 사용하여 접근할 수 있다.
namespace namespaceName {
functionType functionName(...) {
statements;
}
}
또는
namespace namespaceName {
functionType functionName(...);// 이름공간 안에 함수를 선언한다.
}
functionType namespaceName::functionName(...) {// 이름공간 안에 선언된 함수를 정의한다.
statements;
}
Namespace.cpp
namespace KakaoGames {// 이름공간 KakaoGames이다.
void Attack(void);
}
namespace Nexon {// 이름공간 Nexon이다.
void Attack(void);
}
int main(void) {
KakaoGames::Attack();// 이름공간 KakaoGames의 Attack 함수를 호출한다.
Nexon::Attack();// 이름공간 Nexon의 Attack 함수를 호출한다.
return 0;
}
void KakaoGames::Attack(void) {
cout << "카카오의 Attack 함수를 사용합니다." << endl;
}
void Nexon::Attack(void) {
cout << "넥슨의 Attack 함수를 사용합니다." << endl;
}
Namespace.cpp 실행 결과
카카오의 Attack 함수를 사용합니다.
넥슨의 Attack 함수를 사용합니다.
위의 예제에서 10행과 11행의 Attack 함수는 이름이 같지만, 서로 다른 이름공간 안에 정의되어 있기 때문에 별개의 함수이며 컴파일 오류가 발생하지 않는다.
[한줄 요약] 이름공간의 정의와 호출
namespace nameSpaceName { ... }
nameSpaceName::functionName(...);
1.2 이름공간의 중첩과 별칭
이와 더불어 흔하지는 않지만 이름공간을 여러 번 중첩하고 중첩된 이름공간에 별칭을 달아줄 수 있다. 이름공간을 다른 이름공간 안에 삽입하는 것을 이름공간의 중첩이라고 말하는데, 다음과 같은 형식으로 이름공간을 중첩하고 마찬가지로 범위 지정 연산자를 사용하여 중첩된 이름공간의 변수와 함수에 접근할 수 있다.
namespace namespaceNameA {
namespace namespaceNameB {// 중첩된 이름공간B를 정의한다.
...
}
}
namespace AB = namespaceNameA::namespaceNameB;// 이름공간A와 이름공간B를 합쳐 별칭AB을 달아준다.
Namespace2.cpp
#include <iostream>
namespace Terran {// 세 이름공간을 중첩하여 정의한다.
namespace CommandCenter {
int HP = 1500;
namespace SCV {
int HP = 60;
}
}
}
int main(void) {
namespace TC = Terran::CommandCenter;// 이름공간 Terran::CommandCenter를 TC로 별칭을 달아준다.
std::cout << "사령부의 생명력은 "<< Terran::CommandCenter::HP << "입니다." << std::endl;
std::cout << "사령부의 생명력은 "<< TC::HP << "입니다." << std::endl;
std::cout << "건설로봇의 생명력은 " << TC::SCV::HP << "입니다." << std::endl;
return 0;
}
Namespace2.cpp 실행 결과
사령부의 생명력은 1500입니다.
사령부의 생명력은 1500입니다.
건설로봇의 생명력은 60입니다.
1.3 using 키워드와 이름공간의 명시
지금까지 데이터를 입출력할 때 std::cout과 std::cin을 사용했다. 범위 지정 연산자로 미루어보았을 때, 이름공간 std에 cout과 cin이 선언되어 있다는 것을 알 수 있을 것이다. 그런데 cout, cin을 사용할 때마다 std::를 붙여야하는 것이 여간 귀찮은 일이 아니다. 다행히도 이 불편함을 해소할 수 있는데, using 키워드를 선언하면 이름공간에 선언된 변수와 함수의 이름공간 지정을 생략할 수 있다.
using namespaceName::variableName;
using namespaceName::functionName;
using namespace namespaceName; // 해당 이름공간 속 모든 변수와 함수의 이름공간 지정을 생략한다.
Namespace3.cpp
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
// using namespace std;
int main(void) {
int year;
cin >> year;
cout << "카카오 게임즈는 " << year << "년에 상장되었습니다." << endl;
return 0;
}
Namespace3.cpp 실행 결과
2020
카카오 게임즈는 2020년에 상장되었습니다.
위의 예제에서 2, 3, 4행처럼 사용하는 함수마다 using 선언을 하는 것이 번거롭다면, 5행의 using namespace std 선언을 통해서 모든 변수와 함수에 대해 이름공간 std를 생략할 수 있다. 이것은 굉장히 매력적인 선언으로 C++를 학습할 때 기본적으로 사용되지만 그만큼 이름충돌이 발생할 수 있는 여지가 높아진다. 따라서 상황을 적절히 판단해 using 키워드를 사용하기를 바란다.
[한줄 요약] using 키워드와 이름공간 std의 생략
using namespace std;
2. 파일의 분할 문제 풀이
열혈 C++ 프로그래밍 | 문제 01-4 | 파일의 분할
문제 1 헤더 파일, 파일 분할과 관련된 감을 살리기 위해서 앞서 소개한 예제 NameSp2.cpp를 다음과 같이 총 3개의 파일로 분할해서 컴파일해보자. ▶ 헤더 파일: main 함수를 제외한 나머지 두 함수
continue96.tistory.com
'Object Oriented Programming(C++) > 열혈 C++ 프로그래밍' 카테고리의 다른 글
C++ | 02-2 malloc과 free를 대신하는 new와 delete (0) | 2021.08.02 |
---|---|
C++ | 02-1 참조자(Reference) (0) | 2021.08.02 |
C++ | 01-4 인라인 함수(Inline Function) (0) | 2021.07.24 |
C++ | 01-3 매개 변수의 디폴트 값(Default Value) (0) | 2021.07.24 |
C++ | 01-2 함수 오버로딩(Function Overloading) (0) | 2021.07.22 |
댓글