Cpp module00 - 네임스페이스(namespace)

Park Sejin·2021년 9월 4일
0

CppModule

목록 보기
1/2

네임스페이스(namespace)

식별자 충돌

식별자 (identifier)는 변수명, 클래스, 구조체, 열거형, 함수, 클래스 맴버 함수, typedef명 등을 정의의 할때 사용된다.
식별자 작성 규칙 상 같은 범위에서 식별자가 중복되면 안된다.
some이라는 이름으로 변수를 선언했다면 다른 변수뿐만 아니라 함수나 타입의 이름으로도 같은 이름을 사용할 수 없다.

프로그램의 규모가 커지고 여러명이 작업을 할 경우 식별자 충돌이 일어날 가능성이 크다. 그렇기 때문에 언어 차원에서 좀 더 근본적으로 해결할 수 있는 방법이 필요해졌고 이것이 네임스페이스가 필요해진 이유이다.

네임스페이스는 식별자들이 기억되는 영역이며 식별자의 소속 공간이다. 각 공간 영역을 만들고 이 영역 안에 식별자를 그룹화하여 넣어 두면 식별자 충돌 가능성이 대폭 감소된다.
소속 네임스페이스가 다르다면 식별자가 중복되어도 문제없다. 네임스페이스를 정의하는 기본 형식은 다음과 같다.

namespace 네임스페이스 이름
{
    변수나 함수 선언
}

네임스페이스 이름도 식별자의 일종이므로 식별자 작성 규칙에 맞게 만들어야 한다.

네임스페이스에 속한 식별자를 참조할 때는 ::연산자 앞에 네임스페이스의 이름을 붙여 소속을 밝혀야 한다. A::i는 네임스페이스A에 소속된 i를 의미한다.
네임스페이스를 별도로 정의하지 않아도 항상 존재하는 네임스페이스가 있는데 이를 전역 네임스페이스라고 한다. 원래부터 존재하므로 별도의 네임스페이스 이름은 없다.

int i;          // 전역 네임스페이스 소속
namespace A
{
    int i;      // A 소속
}

void func(void)
{
    int i;
    
    i = 1;      // 지역변수 i
    ::i = 2;    // 전역 네임스페이스 i
    A::i = 3;   // A 네임스페이스 i
}

int main(void)
{
    func();
    return (0);
}

네임스페이스 작성 규칙

  1. 네임스페이스의 이름도 일종의 식별자이므로 다른 식별자와 중복되어서는 안된다.
  2. 네임스페이스는 반드시 전역 영역에 선언해야 한다.
  3. 네임스페이스 안에 또다른 네임스페이스를 선언할 수 있다.
namesapce Game
{
    namespace Graphic
    {
        struct Screen{};
    }
    namespace Sound
    {
        struct Sori {};
    }
}
  1. 네임스페이스를 여러번 나누어 선언할 수 있다.
namespace A
{
    double i;
}
namespace A
{
    char name[32];
}
  1. 네임스페이스가 이름을 가지지 않을 수도 있다.
namespace
{
    int internal;
}
  1. 네임스페이스 안에 함수를 정의할 때 헤더 파일에 원형만 선언하고 구현 파일에 함수의 본체를 작성한다.

네임스페이스 사용

네임스페이스 안에 선언된 식별자를 사용하려면 매번 소속 네임스페이스를 밝히고 참조해야 하므로 매우 번거롭다.

int main(void)
{
    MYNS::value = 3;
    MYNS::score = 1.2345;
    MYNS::func();
    return (0);
}

이런 불편함을 해결할 수 있는 세 가지 방법이 제공된다.

  1. using 지시자(directive)

    전역 영역에 using 지시자가 있고 MYNS를 이 영역에서 사용하겠다고 지시했다. 이후 전역 영역에서 MYNS에 속한 식별자는 MYNS:: 없이 바로 사용할 수 있다.
    using 지시자가 영향을 미치는 범위는 이 지시자가 있는 영역에 국한된다.

#include <iostream>

namespace MYNS
{
    int value;
    double score;
    void func(void)
    {
        std::cout << "I am func" << std::endl;
    }
}

using namespace MYNS;

int main(void)
{
    value = 3;
    score = 1.2345;
    func();
    return (0);
}
  1. using 선언(declaration)
    using 지시자는 지정한 네임스페이스의 모든 식별자를 가져오지만 using 선언은 하나의 식별자만 가져온다.
    using 선언이 있는 블록에 대해서만 영향을 미친다.
#include <iostream>

namespace MYNS
{
    int value;
    double score;
    void func(void)
    {
        std::cout << "I am func" << std::endl;
    }
}

int main(void)
{
    using MYNS::value;

    value = 3;
    MYNS::score = 1.2345;
    MYNS::func();
    return (0);
}

void subfunc(void)
{
    MYNS::value = 3;
}
  1. 별명
    네임스페이스는 충돌을 방지하기 위해 긴 이름을 주는데 이름이 너무 길면 번거롭고 코드가 지저분해진다. 이럴 경우 namespace A = VeryVeryLongNameSpaceName;와 같이 짧은 별명을 정의할 수 있다.
name space VeryVeryLongNameSpaceName
{
    struct Person {};
}

int main(void)
{
    namespace A = VeryVeryLongNameSpaceName;
    A::Person P;
}

출처

http://soen.kr/lecture/ccpp/cpp3/34-1-1.htm
http://soen.kr/lecture/ccpp/cpp3/34-1-2.htm
http://soen.kr/lecture/ccpp/cpp3/34-1-3.htm

0개의 댓글