C++/Namespaces

C++ Namespaces

Soul-Learner 2016. 12. 27. 12:52

C++ 프로그래밍, 네임스페이스 ( Namespaces )


C++ 언어의 네임스페이스 개념

C++ 언어에서 네임스페이스(Namespaces)란 말 그대로 이름이 속한 공간(논리적인 그룹)을 의미한다. 여기서 이름은 변수, 함수, 클래스, 또 다른 네임스페이스의 이름을 말한다. 개발자는 이런 이름들이 속한 논리적인 그룹을 지정할 수 있고 그 그룹 안에 선언되는 이름은 중복할 수 없다. 그러나 네임스페이스가 서로 다르다면 동일한 이름을 사용할 수 있다. 

서로 관련성이 있는 코드는 특정 이름을 가진 네임스페이스 안에 선언하면 하나의 논리적인 그룹이 되므로 해당 네임스페이스에 접근하여 그 안에 선언된 엔티티를 사용할 때는 특별한 키워드를 사용하여 선언해야 한다.

네임스페이스 안에는 다양한 엔티티가 선언될 수 있는데, 여기서 엔티티(Entity)란 변수, 함수, 클래스, 객체변수 등 이름으로 표현되는 것들을 말한다


네임스페이스 선언

namespace { /* 엔티티(Entities) 선언 */ }

예)

namespace ns1 { int n = 0;  }


특정 네임스페이스에 접근하여 그 안에 있는 엔티티를 사용할 때

네임스페이스 이름:: 엔티티 이름;  // Scope 연산자( :: )를 사용한다

예)

ns1::n = 10;


다른 네임스페이스를 현재 공간에서 직접 접근할 때(네임스페이스 이름을 제외하고 사용하는 경우)

using 네임스페이스 이름 :: 엔티티 이름;

위와 같이 선언한 후에 현재 영역에 선언된 에티티처럼 사용하면 된다

예)

using ns1::n;

n = 20;   // 네임스페이스 이름을 사용하지 않고도 네임스페이스 안에 있는 변수를 사용할 수 있다


특정 네임스페이스 안에 있는 모든 엔티티들을 네임스페이스 이름 없이 바로 접근하려는 경우

using namespace ns1;   // 이렇게 선언하면 해당 네임스페이스 안에 있는 모든 엔티티들을 직접하는 것처럼 사용할 수 있다

예)

using namespace ns1;

n = 100;


네임스페이스의 이름을 이용하여 그 안에 있는 엔티티를 사용하는 예

#include <iostream>
#include <locale>

using namespace std;

// 네임스페이스 선언. 변수, 함수, 클래스, 객체, 다른 네임스페이스 등이 선언될 수 있다
namespace ns1 {
	int n = 0;			// 변수
	void printNum() {	// 함수
		wprintf(L"ns1, n=%d \n", n);
	}
	class CSample {		// 클래스
		int n;
		public:
		CSample(int n){ this->n = n; }
		void print(){
			wprintf(L"ns1, CSample.n=%d \n", n);
		}
	};

	CSample sample(10);	// 객체
};

namespace ns2 {
	int n = 0;
	void printNum() {
		wprintf(L"ns2, n=%d \n", n);
	}
	class CSample {
		int n;
		public:
		CSample(int n){ this->n = n; }
		void print(){
			wprintf(L"ns2, CSample.n=%d \n", n);
		}
	};

	CSample sample(20);
}

int main() {
	setlocale(LC_ALL, "");
	wcout << L"C++ 네임스페이스(Namespace)" << endl;

	// 네임스페이스에 접근하여 그 안에 있는 변수를 사용하는 예
	ns1::n = 100; // 네임스페이스를 달리하여 동일한 이름의 엔티티가 선언될 수 있다
	ns2::n = 200;

	ns1::printNum(); // 100
	ns2::printNum(); // 200

	ns1::CSample sample1(5); // 네임스페이스 안에 있는 클래스의 객체생성
	ns2::CSample sample2(7);

	// 위에서 생성한 객체의 함수 호출
	sample1.print();	// 5
	sample2.print();	// 7

	// 네임스페이스 안에서 생성된 객체의 함수 호출
	ns1::sample.print();	// 10
	ns2::sample.print();	// 20

	return 0;
}


네임스페이스 안에 있는 특정 엔티티에만 직접 접근하려는 경우 (using 을 이용하여 각각 선언한다)

#include <iostream>
#include <locale>

using namespace std;

// 네임스페이스 선언. 변수, 함수, 클래스, 객체, 다른 네임스페이스 등이 선언될 수 있다
namespace ns1 {
	int n = 0;			// 변수
	void printNum() {	// 함수
		wprintf(L"ns1, n=%d \n", n);
	}
	class CSample {		// 클래스
		int n;
		public:
		CSample(int n){ this->n = n; }
		void print(){
			wprintf(L"ns1, CSample.n=%d \n", n);
		}
	};

	CSample sample(10);	// 객체
};

namespace ns2 {
	int n = 0;
	void printNum() {
		wprintf(L"ns2, n=%d \n", n);
	}
	class CSample {
		int n;
		public:
		CSample(int n){ this->n = n; }
		void print(){
			wprintf(L"ns2, CSample.n=%d \n", n);
		}
	};

	CSample sample(20);
}

int main() {
	setlocale(LC_ALL, "");
	wcout << L"C++ 네임스페이스(Namespace)" << endl;

	// 네임스페이스에 있는 몇개의 엔티티만 직접 접근하려는 경우 using 으로 각각 선언한다
	using ns1::n;			// 기본형 변수
	using ns1::printNum;	// 함수
	using ns2::CSample;		// 클래스
	using ns2::sample;		// 객체

	n = 30;
	printNum();      // 30

	CSample samp(50);
	samp.print();    // 50

	sample.print();  // 20

	// 직접 접근할 수 없는 엔티티는 다음과 같이 네임스페이스 이름을 사용해야 한다
	ns2::n = 70;
	ns2::printNum();

	return 0;
}


특정 네임스페이스 안에 있는 모든 엔티티에 직접 접근하려는 경우 ( using namespace ns1 으로 선언한다)

#include <iostream>
#include <locale>

using namespace std;

// 네임스페이스 선언. 변수, 함수, 클래스, 객체, 다른 네임스페이스 등이 선언될 수 있다
namespace ns1 {
	int n = 0;			// 변수
	void printNum() {	// 함수
		wprintf(L"ns1, n=%d \n", n);
	}
	class CSample {		// 클래스
		int n;
		public:
		CSample(int n){ this->n = n; }
		void print(){
			wprintf(L"ns1, CSample.n=%d \n", n);
		}
	};

	CSample sample(10);	// 객체
};

namespace ns2 {
	int n = 0;
	void printNum() {
		wprintf(L"ns2, n=%d \n", n);
	}
	class CSample {
		int n;
		public:
		CSample(int n){ this->n = n; }
		void print(){
			wprintf(L"ns2, CSample.n=%d \n", n);
		}
	};

	CSample sample(20);
}

int main() {
	setlocale(LC_ALL, "");
	wcout << L"C++ 네임스페이스(Namespace)" << endl;

	// 특정 네임스페이스 안에 있는 모든 엔티티에 직접 접근하려는 경우
	using namespace ns1;

	n = 30;
	printNum();      // 30

	CSample samp(50);
	samp.print();    // 50

	sample.print();  // 10

	// 직접 접근할 수 없는 엔티티는 다음과 같이 네임스페이스 이름을 사용해야 한다
	ns2::n = 70;
	ns2::printNum(); // 70

	return 0;
}


중첩된 네임스페이스네임스페이스 별칭 사용하는 예

#include <iostream>
#include <locale>

using namespace std;

// 네임스페이스 선언. 변수, 함수, 클래스, 객체, 다른 네임스페이스 등이 선언될 수 있다
namespace ns1 {
	int n = 0;			// 변수
	void printNum() {	// 함수
		wprintf(L"ns1, n=%d \n", n);
	}
	class CSample {		// 클래스
		int n;
		public:
		CSample(int n){ this->n = n; }
		void print(){
			wprintf(L"ns1, CSample.n=%d \n", n);
		}
	};

	CSample sample(10);	// 객체

	// 상위 네임스페이스에서는 하위 네임스페이스에 직접 접근 불가(그 반대는 가능)
	namespace ns1sub {
		int n2 = 0;
		void printNum2() {
			wprintf(L"ns2, n2=%d \n", n2);
		}
		class CSample2 {
			int n;
			public:
			CSample2(int n){ this->n = n; }
			void print(){
				wprintf(L"ns2, CSample.n=%d \n", n);
			}
		};

		CSample2 sample2(20);
	}
};

int main() {
	setlocale(LC_ALL, "");
	wcout << L"C++ 네임스페이스(Namespace)" << endl;

	// 중첩 네임스페이스에 접근하는 예
	using namespace ns1; 		// ns1에는 직접 접근가능
	ns1sub::sample2.print(); 	// 하위에 있는 네임스페이스인 ns1sub는 직접 접근안됨

	namespace ns2 = ns1::ns1sub; // 네임스페이스 별칭 선언
	ns2::sample2.print();			// 위에서 선언한 네임스페이스 별칭 이용

	using namespace ns1::ns1sub; // 하위에 있는 네임스페이스에 직접 접근 선언
	sample2.print();

	return 0;
}