본문 바로가기
  • 쓸쓸한 개발자의 공부방
C++

[C++] namespace, using

by 심찬 2021. 8. 2.

 

C++ namespace 개념

 

 

 

 

 

namespace가 필요한 이유

C언어 에서는 여러개의 init() 이 아래와 같이 존재할 때 init() 함수를 구분할 수 없다. (C ++에서도 아래와 같은 코드는 컴파일 에러가 역시 발생한다.) 이를 해결해 줄 수 있는 namespace 개념을 알아두어야 한다.

#include <stdio.h>

void init()
{
    printf("Lego init\n");
}
void init()
{
    printf("Book init\n");
}    

void init()
{
    printf("Default init\n");
}

int main()
{
    init();
}

 

 

아래와 같이 namespace로 함수들을 구분 지을 수 있으며, 동일 init() 함수를 구분된 namespace로 호출할 수가 있다.

그냥 init()을 호출하면 global namepace 가 호출되며 Default init이 출력됨을 확인할 수 있다.

 

#include <stdio.h>

namespace Lego
{
    void init()
    {
        printf("Lego init\n");
    }
}
namespace Book
{
    void init()
    {
        printf("Book init\n");
    }    
}

void init()  // global namespace !!!
{
    printf("Default init\n");
}

int main()
{
    init(); // ???
    Lego::init();
    Book::init();
}

 

 

- C++에서는 프로그램의 크기가 커지면 namespace로 묶어서 관리할 수 있다. 

 

- namespace를 사용하면 기능별로 다른 이름 공간을 사용하기 때문에 함수, 구조체 등의 이름 충돌을 피할 수 있다.

 

 

 

 


 

using

 

using 선언을 통해 접근이 가능하다.

using Lego::init; 으로 선언한 후, init()은 Lego 안의 init()을 호출한다.

#include <stdio.h>

namespace Lego
{
    void init()  { printf("Lego init\n"); }
    void reset() { printf("Lego reset\n");}
}

void init()  { printf("global init\n"); }

int main()
{
    Lego::init();        // 한정된 이름(qualified name) 을 사용한 접근법
                         // 장점 : 오류의 가능성이 낮음
                         // 단점 : 앞에 Lego를 붙여줘야 해서 코딩량이 늘어남.
    
    using Lego::init; // using 선언
    init();
    //reset(); // error 발생함 Lego::init에 대해서만 using 선언을 했고
               // reset()에 대해서는 선언하지 않았기 때문.
}

 

 

 

 

using namespace

 

using 지시어 (directive) 사용 예시

using namespace std;

using namespace Lego;

#include <stdio.h>

namespace Lego
{
    void init()  { printf("Lego init\n"); }
    void reset() { printf("Lego reset\n");}
}

using namespace Lego; // using directive

void init()  { printf("global init\n"); }

int main()
{
    ::init();  // global init 을 명시적으로 불러줌.
    reset();   // reset() dms Lego 안에 하나만 존재하기 때문에 실행됨.
}

using 선언이나 지시어는 함수 안, 밖에서 모두 사용 가능하다.

(함수 안에서 선언하면 당연히 함수 안에서만 유효하다.)


 

잘못된 사용 예시

#include <stdio.h>

namespace Lego
{
    void init()  { printf("Lego init\n"); }
    void reset() { printf("Lego reset\n");}
}

void init()  { printf("global init\n"); }

int main()
{
    using namespace Lego; // using directive
    init();  // compile error!!!
}

using namespace Lego; 를 선언했으나 init()이 global init인지 Lego init인지 모호해서 컴파일 에러 발생한다.

명시적으로 선언을 해주면 해결된다. Lego:: 를 붙여주어 Lego init을 호출하거나 :: 를 붙여 global이 호출되도록 할 수 있다.

 

에러 문구 - error: call of overloaded 'xxx' is ambiguous

친철하게 candidate 정보도 출력해주고 있다.

 


header(.h)파일과 cpp 파일에서 namespace선언 및 사용 방법

 

선언부, 구현부 모두 namespace로 묶어야 한다.

/*======== Lego.h =========*/
namespace Lego
{
    void init();
    void reset();
}

/*======== Lego.cpp =========*/
#include <Lego.h>

namespace Lego
{
    void init()
    {
    }
    void reset()
    {
    }
}
/*======== main.cpp =========*/
#include <Lego.h>

int main()
{
    Lego::init();
}

아래와 같이 구현부 코드에 Lego::init(), Lego::reset() 으로 명시적으로 코드를 넣을 수도 있다.

/*======== Lego.cpp =========*/
#include <Lego.h>

void Lego::init()
{
}
void Lego::reset()
{
}

 

 

 

Hard work!

Hard study!

댓글