이름공간은 "이름을 붙여놓은 공간"이라고 얘기 할수있다.
말 그대로 특정 영역에 이름을 붙여주기 위한 문법적 요소이다.
A,B,C회사가 합동 프로젝트를 진행하기로 하고 파트별로 코드를짠 후 6개월 후에 모였는데!
아뿔싸!! 겹치는 함수가 상당수가 있다.
이는 프로그램을 쏴아악 뜯어 고쳐야할만큼 큰문제다!!!
그래서 이름공간이라는 것이 등장했다!!
한 집에 철수라는 이름 두명이 산다면 철수야!! 부르면 누굴 부르는지 알 수 없다.
그러므로 다른집 201호 철수, 202호 철수 이렇게 구분 해주면
"202호 철수!!" 라고 부르면 구분할수 있다!!
이것이 이름공간의 기본원리이다.
그럼 바로 코드를 보자.

이렇듯
namspace BestComImp1 // bestComImp1의 이름공간의 이름
{
// 이름 공간 내부
}
이렇게 이름공간을 만들고 내부에 함수를 정의하면 이름 충돌이 발생하지 않는다.
메인 함수의 :: 연산자를 가리켜 "범위지정 연산자"라 하며, 그 이름이 의미하듯 이름공간을 지정할 때 사용하는 연산자이다.
#include <iostream>
namespace Best {
void SimpleFunc(void)
{
std::cout<<"Best 가 정의한 함수"<<std::endl;
}
}
namespace est {
void SimpleFunc(void)
{
std::cout<<"est 가 정의한 함수"<<std::endl;
}
}
int main(void)
{
Best :: SimpleFunc();
est :: SimpleFunc();
return 0;
}

함수의 선언과 정의를 분리하는것이 일반적이다!
그렇다면 이름공간 기반에서 함수의 선언과 정의를 구분하는 방법은 무엇일까?

이렇다!
참고로 동일한 이름공간안에 있는 함수를 호출할때에는 이름공간을 명시할 필요가 없다.


이와 같이 이름공간안에 이름공간이 삽입될 수 있다.
총 3개의 num이 존재하는데
std::cout<<Parent::num<<std::endl;
std::cout<<Parent::SubOne::num<<std::endl;
std::cout<<Parent::SubTwo::num<<std::endl;
는 순서대로 2,3,4 가 출력된다.
NameSp2.cpp 를
헤더,소스,메인파일로 분리해라!
name.hpp
//
// name.hpp
// 1_practice
//
// Created by 서희찬 on 2021/04/28.
//
#ifndef name_hpp
#define name_hpp
namespace Best {
void SimpleFunc(void);
}
namespace est {
void SimpleFunc(void);
}
#endif /* name_hpp */
name.cpp
//
// name.cpp
// 1_practice
//
// Created by 서희찬 on 2021/04/28.
//
#include <iostream>
#include "name.hpp"
void Best::SimpleFunc(void)
{
std::cout<<"Best 가 정의한 함수"<<std::endl;
}
void est::SimpleFunc(void)
{
std::cout<<"est 가 정의한 함수"<<std::endl;
}
main.cpp
#include <iostream>
#include "name.hpp"
int main(void)
{
Best :: SimpleFunc();
est :: SimpleFunc();
return 0;
}
자구를 하고 온 나에겐 너무 익숙해져버린 분리닷
우리는 이것의 정확한 정체는 모르지만 이때까지 사용해왔다!
하지만 :: 을 배운 이상!
우리는 좀 더 이 친구들의 정체를 알 수 있다.
- std::cout -> "이름공간 std에 선언된 cout"
- std::cin -> "이름공간 std에 선언된 cin"
- std::endl -> "이름공간 std에 선언된 endl"
이렇듯 우리는 이름공간 std에 cout,endl,cin 이 선언되어 있다는 결론을 내릴 수 있다.
이름 충돌을 막기위해서 C++표준에서 제공하는 다양한 요소들은 이름공간 std 안에 선언되어있다.
이제 ciut,cin,endl 등등을 참조할 때마다 std:: 를 앞에 붙여한다는것을 배웠지만 !
이것이 여간 귀찮지 않다는 생각이든다!
그러나!!!!
추가적인 선언 하나만으로도 이 불편을 해소할 수 있다.
다음 예제를 보자!
#include <iostream>
namespace Hybrid {
void HybFunc(void)
{
std::cout<<"So simple Funciton! "<<std::endl;
std::cout<<"In namespace Hybrid!"<<std::endl;
}
}
int main(void)
{
using Hybrid::HybFunc;
HybFunc();
return 0;
}

using Hybrid::Hyfunc;
은 "Hyfunc를 이름 공간 Hybrid 에서 찾으라" 라는 선언이다!!!
그리고 위에서는 메인함수내에서 선언되어 이 함수안에서만 효력을 가지게 된다.
프로그램 전체영역에 효력을 미치게 할려면 전역변수와 마찬가지로 함수밖에 선언 하면된다.
그럼 밖에 선언한 다음예제를 보자!
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main(void)
{
int num2;
int num = 20;
cout<<"Hello World"<<endl;
cout<<"Hello"<<"World"<<endl;
cout<<num<<" "<<"A";
cout<<" "<<3.14<<endl;
cout<<"num2 : ";
cin>>num2;
return 0;
}

이렇게 일일이 using 선언이 귀찮다면 "이름 공간 std에 선어된 모든 것에 대해 이름공간 지정의 생략"을 명령할 수 있다.
using namespace std;
이는 이름 공간 std에 선언된 모든 것에 접근할때에는 이름공간의 지정을 생략하겠다는 말이다!!
그럼 다음예제를 보자 !
#include <iostream>
using namespace std;
int main(void)
{
int num2;
int num = 20;
cout<<"Hello World"<<endl;
cout<<"Hello"<<"World"<<endl;
cout<<num<<" "<<"A";
cout<<" "<<3.14<<endl;
cout<<"num2 : ";
cin>>num2;
return 0;
}

동일하게 실행된다!

이런식으로 이름공간이 너무~ 많아지면
AAA::BBB::CCC::num1=30;
AAA::BBB::CCC::num2=20;
와 같이 접근 하는 경우 매우 불편하고 폼도 안난다!
그런데 이를
namespace ABC = AAA::BBB::CCC;
와 같이 주면
ABC::num1 = 10;
ABC::num2 = 20;
와 같이 접근 가능하다!!
지역변수의 이름이 전역변수의 이름과 같은 경우,
전역변수는 지역변수에 의해 가려진다는 특징을 기억하는가!?
다음 코드르 보자
int val = 10; // 전역변수
int Simple(void){
int val = 20; // 지역변수
val += 3; // 지역 변수 val의 값 3증가
}
이 경우 전역변수 val에 접근하기 위해서는 어떻게 해야할까?
이때에도
범위 지정 연산자
를 사용하면 된다!!!
int val = 10; // 전역변수
int Simple(void){
int val = 20; // 지역변수
val += 3; // 지역 변수 val의 값 3증
::val += 3; // 전역 변수 val의 값 3증가
}
그럼 이로써 Chapter1에 대한 이론적인 설명을 끝내겠다!!
다음 포스트에서는 프로젝트 하나를 보자