코딩/C와 C++

[C++ 기초 강좌] 7. 네임 공간(namespace)

드리프트 2021. 5. 17. 20:13
728x170

 

 

7. 네임 공간(namespace)

 

우리는 네임 공간에 대해서 몇 번 언급하였다. 그러므로 지금은 그것이 무엇인지에 대해서 알아볼 때이다. 네임 공간은 C++ 언어에 추가된 새롭고도 중요한 기능이다. 그러므로 여러분은 네임 공간이 어떻게 작동하는지에 관해서 알아야 한다.

여러분은 이미 표준 라이브러리에서 사용되는 모든 이름이 std라는 네임 공간 안에서 정의된다는 것을 알고 있다. 이것은 표준 라이브러리 안에서 사용되는 모든 이름에는 추가로 자격을 한정하는 이름인 std가 붙는다는 것을 의미한다. 그러므로 예를 들어, cout는 실제로 std::cout이다. 우리는 이러한 사실을 간단한 예를 통해서 살펴볼 수 있다 이 예에서는 변수를 글로벌 범위로만 사용한다. 왜냐하면, 우리는 네임 공간이 어떻게 작동하는지를 살펴보고자 하기 때문이다.

 

// ex2_08.cpp
// 네임 공간 이름 사용하기

#include <iostream>

int value = 0;

int main()
{
	std::cout << "enter an integer: ";
    std::cin >> value;
    std::cout << "\nYou entered " << value
              << std:: endl;
              
    return 0;
}
    

std에 대해서 using 명령을 사용하지 않았다는 것을 명심하라. 우리가 std 네임 공간으로부터 사용하고 있는 이름을 모두 제한하고 있기 때문에 여기서는 그럴 필요가 없다. 약간 이상하지만, 여기서 우리는 cout를 정수 변수의 이름으로서 사용할 수 있다. cout 그 자체는 std::cout와는 다르기 때문에 혼동될 염려가 없다. 그럼으로써, 네임 공간은 프로그램의 한 부분에서 사용되는 이름을 다른 부분에서 사용되는 이름과 분리하는 방법을 제공하는 것이다. 이러한 측면은 프로그램의 각기 다른 부분을 맡은 몇 팀의 프로그래머들이 연관된 커다란 프로젝트의 경우에 매우 유용하댜 각 팀은 그 팀만의 네임 공간 이름을 가질 수 있으므로 다른 종류의 함수에 대해서 실수로 동일한 이름을 사용할 염려가 없는 것이다.

물론, 여러분은 여러분만의 네임 공간 이름을 가지는 네임 공간을 정의할 수 있다. 그렇게 하는 방법에 대해서 살펴본다.

 


7.1 네임 공간 선언하기


여러분은 네임 공간을 선언할 때 다음과 같이 namespace 키워드를 사용한다.

namespace myStuff
{
    // myStuff 네임 공간 안에 위치시키고자 하는 코드
}


여러분은 함수 안에서는 네임 공간을 선언할 수 없다. 네임 공간은 다른 방법으로 사용되기 위한 것이다. 여러분은 네임 공간을 사용하여 함수, 변수, 그리고 다른 엔티티를 여러분의 프로그램에 포함시킨다. 그러나 여러분은 main을 네임 공간 안에 위치시키면 안 된다. 실행이 시작되는 main() 함수는 항상 글로벌 네임 공간 범위에 있어야 한다. 그렇지 않으면 컴파일러는 그것을 인식하지 않을 것이다.


우리는 이전의 샘플에 사용했던 value 변수를 네임 공간 안에 위치시킬 수 있다.

// EX2 09.CPP
// 네임 공간 선언하기

#include <iostream>

namespace myStuff
{
   int value = O;
}

int main()
{

    std::cout << "enter an integer: ";
    std::cin >> myStuff::value;
    std::cout << "\nYou entered " << myStuff::value
                << std::endl;
return O;
}

myStuff 네임 공간은 범위를 정의하고, 네임 공간 범위 안에 있는 모든 것은 네임 공간 이름을 가지는 것으로 제한된다. 네임 공간 안에서 선언된 이름을 바깥에서 참조하려면 여러분은 그것을 네임 공간 이름으로 제한해야 한다. 네임 공간 범위 안에서는 그 안에서 정의된 모든 이름을 그러한 제한 없이 참조할 수 있다. 즉, 그것들은 모두 동일한 가족의 한 부분이 된다. 이제, 우리는 이름값에 우리의 네임 공간 이름인 myStuff를 붙여야 한다. 프로그램은 컴파일되지 않을 것이다. 이제, main() 함수는 두 개의 각기 다른 네임 공간 안에 있는 이름을 참조할 것이다. 그리고 일반적으로, 여러분은 프로그램에서 필요한 만큼의 네임 공간을 가질 수 있다. 우리는 using 명령을 사용함으로써 value를 제한하지 않아도 된다.

// EX2_10.CPP
// using 명령 사용하기

#include <iostream>
namespace myStuff
{
    int value = O;
}

using namespace myStuff;  // myStuff 안에 있는 모든 이름들을 사용 가능하게 만듦.

int main()
{

    std::cout << "enter an integer: ";
    std::cin >> myStuff::value;
    std::cout << "\nYou entered " << myStuff::value
                << std::endl;
return O;
}

또한, 여러분은 std에 대해서도 using 명령을 사용할 수 있다. 그러므로 여러분은 표준 라이브러리의 이름을 제한할 필요가 없다. 그러나 이것은 네임 공간의 전체적인 개념을 흐리게 한다. 일반적으로, 여러분이 네임 공간을 프로그램에서 사용한다면 여러분은 using 명령을 여러분의 모든 프로그램에 추가하면 안 된다. 왜냐하면, 여러분은 애당초 네임 공간 때문에 걱정하지 않는 것이 좋기 때문이다. 그렇게 말했으므로 우리는 std에 대한 using 명령을 우리의 모든 샘플에 추가하여 코드가 난잡하게 보이지 않게 하고, 여러분이 더 읽기 쉽도록
할 것이다. 여러분이 난잡한 코드를 발생시키지 않는 새로운 프로그래밍 언어를 사용한다면 실제적으로 그것이 얼마나 유용하든지, 않든지에 상관없는 것이다.

 

7.2 여러 개의 네임 공간

실제의 프로그램에서는 여러 개의 네임 공간을 포함하게 된다. 여러분은 어떤 하나의 주어진 이름을 사용하여 네임 공간을 여러 번 선언할 수 있다. 그리고 각각의 네임 공간에 대한 블록의 내용은 동일한 네임 공간 안에 위치한다. 예를 들어, 여러분은 두 개의 네임 공간을 가지는 프로그램을 작성할 수 있다.

namespace sortStuff
{
  // 여기에 있는 모든 것들은 sortStuff 네임 공간 안에 있다.
}

namespace calculateStuff
{
  // 여기에 있는 모든 것들은 calculateStuff 네임 공간 안에 있다.
  // sortStuff로부터의 이름들을 참조하려면 그것들은 조건별로 제한되어야 한다.
}

namespace sortStuff
{
  // 이것은 sortStuff 네임 공간의 연속이다.
  // 그러므로 여기에서부터 여러분은 첫 번째 sortStuff 네임 공간에 있는 이름들을
  // 제한하지 않고서도 참조할 수 있다.
}

네임 공간을 주어진 이름으로 두 번째로 선언하는 것은 단지 첫 번째의 연속에 불과하다. 그러므로 여러분은 첫 번째 네임 공간 블록 안에 있는 이름을 두 번째에서 그 이름을 제한하지 않고서도 참조할 수 있다. 그것들은 모두 동일한 네임 공간 안에 위치한다. 물론, 여러분은 보통 일부러 소스 파일을 이러한 방식으로 구성하지는 않을 것이다. 그러나 여러분이 프로그램 안에 포함시키는 헤더 파일에서는 매우 자연스럽게 그렇게 될 수 있다. 예를 들어, 여러분이 다음과 같은 것을 가지고 있다고 생각해 보자.

#include <iostream>     // std 네임 공간 안에 있는 내용
#include "myheader.h"  // myStuff 네임 공간 안에 있는 내용
#include <string>      // std 네임 공간 안에 있는 내용

//  등등...


우리는 이 강좌 시리즈에서 각기 다른 종류의 #include 명령에 대해서 살펴볼 것이다. 여기서 iostream과 string은 표준 라이브러리 헤더이고, myheader.h는 프로그램 코드를 포함하는 헤더 파일을 나타낸다. 우리는 이전의 그림에서와 정확하게 동일한 네임 공간을 가지고 있는 상황이 되었다.

이것은 여러분에게 네임 공간이 어떻게 작동하는지에 대한 기본적인 지식을 제공한다. 우리가 여기서 다룬 것보다 더 많은 네임 공간이 있다. 그러나 여러분이 여기서 다룬 내용을 이해한다면 여러분이 필요로 할 때 어렵지 않게 네임 공간에 대한 더 많은 것을 얻을 수 있을 것이다.

 


C++ 기초 강의 1 ~ 7 요약

 

C++ 기초 강의 시리즈 1 ~ 7에서 우리는 C++에서의 계산 작업에 관한 기본적인 사항을 다루었다. 우리는 언어에서 제공되는 모든 기본적인 형식과 그러한 형식들을 직접적으로 다루는 모든 연산자에 대해서 배웠다. 이제까지 우리가 다루었던 내용에 대한 핵심은 다음과 같다.

  • C++로 써진 프로그램은 적어도 하나의 main()이라고 불리는 함수로 구성된다.
  • 함수의 실행 부분은 중괄호 사이에 포함되어 있는 문장들로 구성된다.
  • C+ +에서의 문장은 세미콜론으로 끝난다.
  • 변수 또는 함수와 같이 C+ +에서 이름을 가지는 객체는 문자와 숫자로 구성되는 이름을 가질 수 있다. 이름의 첫 번째는 문자이며, 밑줄도 문자로 인식된다. 이름에서는 대 · 소문자의 구벌이 있다.
  • 프로그램에서 변수 등과 같은 모든 객체의 이름을 정할 때는 C++에서 예약되어 있는 단어와 같은 이름을 가질 수 없다.
  • C+ + 안에 있는 모든 상수와 변수는 하나의 형식을 가지게 된다. 기본적인 형식은 char, int, long, float, 그리고 double이다.
  • 선언문에서 정의되는 변수의 형식과 이름은 세미콜론으로 끝난다. 변수는 선언문에서 초기값을 가질 수 있다.
  • 여러분은 const 수정자를 사용함으로써 기본적인 형식을 가지는 변수의 값을 보호할 수 있다. 이렇게 함으로써 프로그램 안에서 변수를 직접적으로 수정하는 것을 막을 수 있다: 그리고 상수의 값이 변경된 곳에서 컴파일러 에러 메시지를 얻을 수 있다.
  • 디폴트로, 변수는 자동 변수가 된다. 이것은 그 변수가 선언된 곳으로부터 그것의 정의된 범위가 끝나는 곳까지만 존재한다는 것을 의미한다. 범위가 끝나는 곳은 그 변수의 선언 이후에 닫힌 중괄호(})로 표시된다.
  • 변수는 static으로서 선언될 수 있다 그러한 경우, 그 변수는 프로그램의 수명 동안에 존재한다. 그것은 단지 그것이 정의된 범위 안에서만 액세스 될 수 있다.
  • 하나의 프로그램 안에서 변수는 모든 블록의 바깥쪽에서 선언될 수 있다. 그러한 경우, 그 변수는 글로벌 네임 공간 범위를 갖는다. 글로벌 네임 공간 범위를 갖는 변수는 전체 프로그램 안에서 액세스 될 수 있다. 그러나 로컬 변수가 동일한 이름으로 글로벌 변수로서 존재하는 곳은 제외된다. 그러나 그렇더라도 범위 분석 연산자를 사용하면 여전히 사용할 수 있다.
  • 표준 라이브러리는 여러분의 프로그램에서 사용될 수 있는 함수와 연산자를 포함한다. 그러한 함수와 연산자들은 std 네임 공간 안에 포함된다. 이 네임 공간은 보통 using 명령을 사용하여 액세스 된다. 네임 공간 안에 있는 개벌적인 객체들은 범위 분석 연산자를 사용하여 액세스 될 수 있다.
  • 네임 공간은 그 안에서 선언된 각각의 이름이 네임 공간 이름에 의해서 제한되는 범위를 정의한다. 네임 공간 밖에서 이름을 참조하려면 그 이름이 그러한 자격을 가지고 있어야 한다.
  • lvalue는 할당 문의 왼쪽에 나타날 수 있는 하나의 객체이다 const 변수가 아닌 것들이 lvalue의 예이다
  • 여러분은 각기 다른 형식을 가지는 변수와 상수를 하나의 표현 안에서 사용할 수 있다. 그러나 그것들은 필 요한 곳에서 는 공통적인 형식으로 자동적으로 변환된 다. 필요한 경우에는 할당 문의 오른쪽에 있는 형식을 왼쪽에 있는 형식으로 변환하는 작업도 수행된다 이때 왼쪽에 있는 형식이 오른쪽에 있는 형식이 가지고 있는 것과 동일한 정보를 포함할 수 없을 때 정보의 손실이 발생할 수 있다. int로 변환된 double 또는 short로 변환된 long 이 그 예이다.
  • 여러분은 어떤 한 표현의 값을 다른 형식으로 명시적으로 변환시킬 수 있다 변환 작업에서 정보의 손실이 발생할 겨우 여러분은 항상 명시적으로 값을 변환시켜야 한다. 또한, 여러분이 원하는 결과를 얻기 위해서 명시적인 변환 작업을 지정해야 할 경우도 있다.
  • typedef 키워드는 여러분이 다른 형식에 대한 동의어를 정의할 수 있도록 한다.


비록 우리가 모든 기본적인 형식들에 대해서 다루었지만, 이것이 모든 것이라는 생각을 하지 말라. 우리가 보게 되겠지만, 기본적인 set을 기반으로 하는 더 복잡한 형식도 있다. 그리고 궁극적으로, 여러분만의 형식을 생성하게 될 것이다.


그리드형