네임스페이스
네임스페이스의 개념
네임스페이스는 C++에서 이름 충돌 문제를 해결하고 관련된 식별자들을 그룹화하기 위한 메커니즘입니다.
대규모 프로젝트나 라이브러리 작성 시 특히 유용합니다.
주요 특징
- 이름 충돌 방지
- 코드의 모듈화 촉진
- 관련 기능들의 논리적 그룹화
네임스페이스 정의
네임스페이스는 다음과 같이 정의합니다.
namespace MyNamespace {
// 변수, 함수, 클래스 등 선언
int myVariable;
void myFunction() {
// 함수 내용
}
class MyClass {
// 클래스 정의
};
}
네임스페이스 사용 방법
- 완전한 이름 사용 (Fully qualified name)
MyNamespace::myVariable = 10;
MyNamespace::myFunction();
- using 선언 (using declaration)
using MyNamespace::myVariable;
myVariable = 10; // MyNamespace:: 접두사 없이 사용 가능
- using 지시어 (using directive)
using namespace MyNamespace;
myVariable = 10; // 네임스페이스 내 모든 이름을 접두사 없이 사용 가능
myFunction();
중첩 네임스페이스
네임스페이스는 다른 네임스페이스 안에 중첩될 수 있습니다.
namespace Outer {
namespace Inner {
void foo() {
// 함수 내용
}
}
}
// 사용
Outer::Inner::foo();
C++ 17부터는 다음과 같이 간단히 표현 가능합니다.
namespace Outer::Inner {
void foo() {
// 함수 내용
}
}
익명 네임스페이스
이름 없는 네임스페이스로, 해당 파일 내에서만 접근 가능한 요소를 정의할 때 사용합니다.
namespace {
int privateVariable; // 이 파일 내에서만 접근 가능
}
네임스페이스 별칭
긴 네임스페이스 이름에 대한 별칭을 정의할 수 있습니다.
namespace LongNamespaceName {
void foo() {}
}
namespace ns = LongNamespaceName;
ns::foo(); // LongNamespaceName::foo()와 동일
표준 라이브러리와 std 네임스페이스
C++ 표준 라이브러리의 모든 요소는 std 네임스페이스에 정의되어 있습니다.
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
실습
- 간단한 네임스페이스 정의 및 사용
#include <iostream>
namespace Mathematics {
int add(int a, int b) {
return a + b;
}
}
namespace Physics {
double calculateVelocity(double distance, double time) {
return distance / time;
}
}
int main() {
std::cout << "5 + 3 = " << Mathematics::add(5, 3) << std::endl;
std::cout << "Velocity: " << Physics::calculateVelocity(100.0, 10.0) << " m/s" << std::endl;
return 0;
}
- 중첩 네임스페이스 예제
#include <iostream>
namespace University {
namespace ComputerScience {
void printDepartment() {
std::cout << "Computer Science Department" << std::endl;
}
}
namespace Mathematics {
void printDepartment() {
std::cout << "Mathematics Department" << std::endl;
}
}
}
int main() {
University::ComputerScience::printDepartment();
University::Mathematics::printDepartment();
return 0;
}
- using 선언과 지시어의 차이점 실습
#include <iostream>
namespace A {
void foo() { std::cout << "A::foo()" << std::endl; }
void bar() { std::cout << "A::bar()" << std::endl; }
}
namespace B {
void foo() { std::cout << "B::foo()" << std::endl; }
}
int main() {
// using 선언
using A::foo;
foo(); // A::foo() 호출
// B::foo(); // 오류: 모호함
// using 지시어
using namespace B;
// foo(); // 오류: A::foo()와 B::foo() 사이의 모호함
B::foo(); // 명시적으로 B::foo() 호출
bar(); // A::bar() 호출 (B에는 bar가 없으므로 모호하지 않음)
return 0;
}
주의사항
1. 전역 네임스페이스 오염 방지
- 가능한 한 전역 네임스페이스에 직접 정의하는 것을 피하세요.
2. using 지시어의 과도한 사용 주의
- 특히 헤더 파일에서 using 지시어 사용은 피해야 합니다.
연습 문제
Geometry
라는 네임스페이스를 만들고, 그 안에 원의 면적과 둘레를 계산하는 함수를 정의하세요. 그리고 main 함수에서 이를 사용하는 프로그램을 작성하세요.- 두 개의 네임스페이스
MyMath
와YourMath
를 만들고, 각각에 동일한 이름의 함수 'add'를 정의하세요. main 함수에서 두 네임스페이스의 add 함수를 모두 사용하는 프로그램을 작성하세요. - 중첩 네임스페이스를 사용하여
Company::Department::Team
의 구조를 만들고, 각 레벨에 적절한 함수나 변수를 정의하세요. 이를 main 함수에서 사용하는 예제를 작성하세요.
참고자료
- C++ 네임스페이스 : https://en.cppreference.com/w/cpp/language/namespace
- C++ Core Guidelines on namespaces : http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rs-namespace
- Effective C++ : Item 28 "Avoid returning "handles" to object internals" by Scott Meyers (네임스페이스와 관련된 설계 고려사항)