책 2장의 네임스페이스와 변수중에 네임스페이스만 다뤄볼까합니다.

 

우선 네임스페이스는 C에서는 제공하지 않지만, C++에서만 제공되는 독특한 기능입니다. 네임스페이스를 직영하면 '이름 공간'이란 의미로, 클래스와 구조체 그리고 함수나 변수를 식별하는데 사용됩니다.

 

예를 들면, 전 세계에서 통용되는 프로그램을 만들 때 대한민국과 미국 중국에서 각각 다른 프로그램을 만든다고 가정하면 'money'라는 변수를 서로 사용할 수 있습니다. 이 때 각 국에서 만든 프로그램을 하나로 합친다면 함수나 변수의 이름에 의해 혼선이 발생하게 됩니다.

이를 구분지어주기위한게 바로 네임스페이스입니다.

 

 

네임스페이스의 선언

네임스페이스는 일반적으로 main함수 이전에 선언하는 것이 옳습니다. namespace라는 명령어를 이용하여 사용합니다.

 

선언 형식은 다음과 같습니다. namespace (네임스페이스 이름) { ... }

namespace sample {
int a = 5;
void print() {
	std::cout << a << std::endl;
}
}

여기서 평소와는 다른 점이 인덴트를 사용하지 않았습니다. 그 이유는 통상적으로 네임스페이스 내부 변수 이름이나 함수 이름이 길어지다보니 인덴트를 사용하면 문장의 길이가 길어져서 관용적으로 사용하지 않는다고 합니다.

네임스페이스의 사용

네임스페이스를 다루면서 '식별자'라는 이름을 많이 사용할 것입니다. 식별자는 개별 변수나 클래스와 같은 데이터 타입 그리고 함수 등을 말합니다.

식별자의 정규화된 이름

앞서 1장에서 콘솔 출력을 할 때 cout 앞에 std::를 붙이는 것을 볼 수 있다. std는 standard의 약자로 표준 네임스페이스를 말합니다. 이를 사용하기 위해서 범위 확인 연산자(::)를 이용하여 사용할 수 있습니다.

 

#include <iostream>
#include <string>

int main() {
	std::cout << "HelloWorld!\n";
	std::string str;
	std::cin >> str;
	return 0;
}

cout, cin, string 모두 std 네임스페이스에 속합니다.

 

using 선언문

using을 이용하여 사용하고자 하는 식별자를 사전에 선언할 수 있다.

선언 형식은 다음과 같습니다. using (네임스페이스영역)::(식별자)

 

#include <iostream>

using std::cout;
using std::endl;

int main() {
	cout << "HelloWorld!" << endl;
	return 0;
}

using 선언을 하고 항상 세미콜론(;)을 입력하는 것을 잊지말아야합니다.

 

using 지시문

대부분 C++를 시작한지 얼마 안된 개발자라면 using 지시문을 사용하는 경우가 많습니다. 하지만 책에서는 공동으로 개발하는 환경이나, 어느정도 규모가 있는 개발이라면 사용하지 않는 것을 권하고 있습니다.

 

using지시문은 프로그램에서 식별자를 찾을수 없다면 지시문이 제공하는 네임스페이스를 붙이는 것을 실행합니다.

 

선언 형식은 다음과 같습니다. using namespace (네임스페이스 이름)

 

#include <iostream>
#include <vector>

using namespace std;

int main() {
	cout << "HelloWorld!" << endl;
	vector<int> vec;
	return 0;
}

using지시문을 사용하면 std에서 제공하는 cout, endl, vector 말고도 더욱 다양한 식별자를 이용할 수 있습니다.

 

별칭 네임스페이스

네임스페이스의 이름이 길거나 여러 개의 네임스페이스를 연결하여 사용하는 경우에 사용할 수 있습니다.

 

예를 들면

#include <iostream>

namespace foo {
	namespace bar {
		namespace zav {
			int n = 41;
		}
	}
}

namespace fbz = foo::bar::zav;

int main() {
	std::cout << fbz::n << std::endl;
	return 0;
}

napespace fbz = foo::bar::zav 로 내부네임스페이스를 fbz로 정의하여 사용할 수 있습니다.

 

또는 네임스페이스의 이름이 긴 경우도 가능합니다.

namespace alias_name = qualified-namespace;

qulified-namespace라는 긴 이름의 네임스페이스를 alias_name으로 간략하게 사용이 가능합니다.

 

 

내부 네임스페이스

네임스페이스안에 하나 이상의 네임스페이스 선언이 가능합니다. 별칭네임스페이스에서 잠깐 나왔던 fbz가 이에 해당된다.

 

만약 내부 네임스페이스에 같은 식별자를 사용하면 어떻게 될까?

 

예를 들면

#include <iostream>

namespace sample {
void sampleMethod() {
    std::cout << "sampleMethod in smaple namesapce" << std::endl;
}

namespace nested {
    void sampleMethod() {
        std::cout << "sampleMdethod in nested" << std::endl;
    }
}
}

int main() {
	sample::sampleMethod();
	sample::nested::sampleMethod();
	return 0;
}

여기서 내부 네임스페이스의 식별자는 관용적으로 인덴트를 사용한다고 합니다.

 

위 예시의 출력 값은

sampleMethod in smaple namesapce
sampleMdethod in nested

예상대로 네임스페이스의 구분대로 출력이된다.

 

 

전역 네임스페이스

main함수는 어떠한 네임스페이스에 속해있지 않습니다. 따라서 컴파일러는 main함수 안의 내용을 '전역 네임스페이스'에 만들어 처리하게 됩니다.

 

전역 네임스페이스를 호출하는 방법은 두가지가 있는데,

첫번째는 ::SampleFunction(x);

두번째는 SampleFunction(x);

 

두번째는 우리가 항상 쓰던 방식입니다. 다만 여기서 알아야 할 것은 main함수 안의 네임스페이스 선언이 안된 식별자들을 전역 네임스페이스에 넣어서 실행시킨다는 점입니다. 

 

예를 들면

#include <iostream>

void print() {
    std::cout << "print complete." << std::endl;
}

int main() {
    ::print();
    print();

    return 0;
}

 

위 예시의 출력 값은

print complete.
print complete.

이것으로 평소에 우리가 쓰던 방식들이 전역 네임스페이스로 기록되어 사용된 다는 것입니다.

 

 

무명 네임스페이스

무명 네임스페이스는 호출하는 방법이 전역 네임스페이스와 동일하나 전혀다르다는 것을 알아야합니다.

 

선언하는 방법은 기존의 namespace에서 이름만 빼주면 됩니다.

 

예를 들면

#include <iostream>
#include <cstdlib>

//무명 네임스페이스
namespace {
void sampleMethod() {
    std::cout << "sampleMethod in unamed namespace" << std::endl;
}
}

//일반 네임스페이스
namespace sample {
void sampleMethod() {
    std::cout << "sampleMethod in smaple namespace" << std::endl;
}

namespace nested {
    void sampleMethod() {
        std::cout << "sampleMdethod in nested" << std::endl;
    }
}
}

int main() {
    sample::sampleMethod();
    sample::nested::sampleMethod();
    ::sampleMethod();
    sampleMethod();

    return 0;
}

 

위 예시의 출력 값은

sampleMethod in smaple namespace
sampleMdethod in nested
sampleMethod in unamed namespace
sampleMethod in unamed namespace

::sampleMethod()와 sampleMethod()처럼 호출은 전역 네임스페이스와 비슷하나 전혀다르다는 것을 알 수 있습니다. 

 

 

마무리

2장에서는 네임스페이스에 관해 배워보았습니다. 다음 장에서는 변수에 대하여 배워보도록 하겠습니다.

'코딩공부 > C&C++' 카테고리의 다른 글

[C++] #01장 C++의 기본 입출력 cout / cin  (0) 2019.12.23
Mac에서 VSCode C/C++ 세팅  (3) 2019.12.06