icon안동민 개발노트

네임스페이스


네임스페이스의 개념

 네임스페이스는 C++에서 이름 충돌 문제를 해결하고 관련된 식별자들을 그룹화하기 위한 메커니즘입니다.

 대규모 프로젝트나 라이브러리 작성 시 특히 유용합니다.

 주요 특징

  1. 이름 충돌 방지
  2. 코드의 모듈화 촉진
  3. 관련 기능들의 논리적 그룹화

네임스페이스 정의

 네임스페이스는 다음과 같이 정의합니다.

namespace MyNamespace {
    // 변수, 함수, 클래스 등 선언
    int myVariable;
    void myFunction() {
        // 함수 내용
    }
    class MyClass {
        // 클래스 정의
    };
}

네임스페이스 사용 방법

  1. 완전한 이름 사용 (Fully qualified name)
MyNamespace::myVariable = 10;
MyNamespace::myFunction();
  1. using 선언 (using declaration)
using MyNamespace::myVariable;
myVariable = 10;  // MyNamespace:: 접두사 없이 사용 가능
  1. 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;
}

실습

  1. 간단한 네임스페이스 정의 및 사용
#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;
}
  1. 중첩 네임스페이스 예제
#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;
}
  1. 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 지시어 사용은 피해야 합니다.

연습 문제

  1. Geometry라는 네임스페이스를 만들고, 그 안에 원의 면적과 둘레를 계산하는 함수를 정의하세요. 그리고 main 함수에서 이를 사용하는 프로그램을 작성하세요.
  2. 두 개의 네임스페이스 MyMathYourMath를 만들고, 각각에 동일한 이름의 함수 'add'를 정의하세요. main 함수에서 두 네임스페이스의 add 함수를 모두 사용하는 프로그램을 작성하세요.
  3. 중첩 네임스페이스를 사용하여 Company::Department::Team의 구조를 만들고, 각 레벨에 적절한 함수나 변수를 정의하세요. 이를 main 함수에서 사용하는 예제를 작성하세요.

 참고자료