본문 바로가기
Language & Framework & GIT/C++

[씨앤씨뿔]C++/ namespace - 2

by veganwithbacon 2023. 4. 13.
반응형

✅namespace 요소 접근 방법

1️⃣ 한정된 이름(qualified name)을 사용한 접근

namespace::요소

이와 같이 namespace를 입력하고 "::"을 통해 네임스페이스 내부에 있는 요소에 접근하는 방법이 있다.

한정된 이름을 사용한 접근이라 부르며, 제일 명확한 방법이기도 하다.

 

코드가 늘어지고 번거롭기도 하지만, 충돌을 피할 수 있는 확실한 방법이며, 소속 또한 명확해진다.

#include<iostream>
using namespace std;

namespace A{
	void printAll(){
    	cout << "A의 printAll 함수" << endl;
        }
}

namespace B{
	void printAll(){
    	cout << "B의 printAll 함수" << endl;
        }
}

int main(void)
{
    //printAll 함수 출력
    A::printAll();
    B::printAll();
    
    return 0;
}

이처럼 namespace를 통해 이름을 지정해주고  A::~ / B::~와같이 접근할 수 있다.

    A::printAll();
    B::printAll();

과 같이 사용하면 된다.


2️⃣전역 using 선언(declaration)을 통한 접근

using namespace::요소;

와 같이 명시해주고 사용한다

특정 space에서 이름 없어 요소를 호출하고 싶을 때 사용된다.

namespace 소속에 있는 변수 하나,함수 하나 이렇게 하나씩 지정해 사용하게 된다.

#include <iostream>
using namespace std;
 
namespace ABC {
    int MAX_CNT = 10;
    
    void init() {
        cout << "ABC의 init() 함수" << endl;
    }
 
    void print() {
        cout << "ABC의 print() 함수" << endl;
    }
}
 
using ABC::init;
 
int main(void)
{
    init();      // 가능
 
    ABC::init(); // 가능
    
 
    ABC::print();
    cout << ABC::MAX_CNT << endl;
    //print();                  호출 불가
    //cout << MAX_CNT << endl;  호출 불가    
 
    return 0;
}

예제를 보면  using ABC::init 을 이용해서 이름공간 ABC 안에 있는 init 함수를 전역 using 선언을 해줬다.
이렇게 되면 해당 파일 어디에서든 ABC::init() 함수를 ABC::을 떼고 init()라는 이름으로 호출 수 있다.

 

init();으로 호출이 가능하며, 물론 ABC::init()으로 호출해도 상관은 없다.

 

그러나 using 선언을 해준 init과는 달리,
using 선언을 하지 않은 ABC 네임스페이스의 다른 변수나 함수 print(), MAX_CNT는 ABC::를 꼭 붙여서 사용해야한다.


3️⃣전역 using 지시어(directive)를 통한 접근

특정 요소만 접근을 가능하게 하는 using선언과는 달리

using 지시어는 해당 namespace 내부에 있는 모든 요소의 접근을 가능하게 해준다.

 

using namespace 네임스페이스명;

 

위와 같이 using namespace 네임스페이스명; 으로 선언하면 해당 명의 모든 요소에 "네임스페이스::"를 떼고 접근 가능하게 된다.

#include <iostream>
using namespace std;
 
namespace ABC {
    int MAX_CNT = 10;
    
    void init() {
        cout << "ABC의 init() 함수" << endl;
    }
 
    void print() {
        cout << "ABC의 print() 함수" << endl;
    }
}
 
using namespace ABC; //ABC 이름공간 제약없이 접근 가능
 
int main(void)
{
    init();
    print();                    
    cout << MAX_CNT << endl;
 
    return 0;
}

예제처럼 using namespace ABC를 선언했기 때문에, main 함수 내부에서 처럼 ABC 이름 공간 안에 있는 모든 요소에 "이름공간::" 이 없이 접근이 가능한 것을 확인할 수 있다.

 

2번과 3번은 아마 사용 시 메모리 할당 때문에 나뉘는 것 같은데, 확실하진 않아서 좀더 공부해보고 해당 포스트에 내용을 추가하던가 포스팅을 하나 더 하도록 하겠다. 

 

 

4️⃣함수 내부 using 선언(declaration)을 통한 접근

c로 치자면 2번이 전역변수, 해당 내용이 지역변수라고 생각할 수 있다.

2번의 함수 using 선언은 함수 필드 밖에 하기 때문에 모든 함수에서 접근이 가능하지만,

해당 내용에서는 함수 내부에서 using을 선언하기 때문에, 해당 스코프 내에서만 적용이 가능한 것이다.

 

--------------------------------------------------------------------------------------------------------------------------------

함수(~~)

{

~~~~~~

 

 using 네임스페이스명::요소;

 //  선언 이후에는 네임스페이스명을 생략하고 사용가능(하지만 해당 함수 내부에 한정됨)

 

}

-------------------------------------------------------------------------------------------------------------------------------

함수 1에서만 using을 사용하고 타 함수에서는 using을 적용하고 싶지 않을 때, 사용하면 된다.

#include<iostream>
using namespace std;

namesapce gyochon{

	void honeycombo(){
    	cout << "가격 왜 자꾸 올리는 거야 gyochon공간의 honeycombo()함수" << endl;
    }
}

int main(void)
{
	gyochon::honeycombo();
    //honeycombo();  //불가능
    
    using gyochon::honeycombo; // 선언했으므로 아래로는 honeycombo() 바로 사용 가능
    honeycombo(); //가능
    
    return 0;
}
//저는 뿌링클이나 고추바사삭이 더 좋습니다

//다른 함수
void example(){
	//honeycombo(); 불가능
    gyochon::honeycombo(); //가능
}

main 함수 내부에

gyochon 이름 공간에 honeycombo 함수를

using gyochon::honeycombo를 선언하기 전에는 gyochon::honeycombo()와 같이만 호출 가능한데,

using gyochon::honeycombo를 선언하고 난 후부터는 honeycombo() 와 같이 선언이 가능한 것을 확인할 수 있다.

 

하지만, 전역 using 선언과는 다르게 example() 내에서는honeycombo(); 호출이 불가능하다는 것도 확인할 수 있다.


5️⃣함수 내부 using 지시어(directive)를 통한 접근

3번과 같이 "전역 using 지시어"와의 다른 점은 똑같이 지역변수처럼 작용하게 한다는 것이다.

적용 범위가 전체에서 하나의 함수 내부로 좁혀지는 것이다.

 

--------------------------------------------------------------------------------------------------------------------------------

함수(~~)

{

~~~~~~

 

 using namespace 네임스페이스명;

 //  선언 이후에는 네임스페이스명을 생략하고 사용가능(하지만 해당 함수 내부에 한정됨)

 

}

-------------------------------------------------------------------------------------------------------------------------------

#include<iostream>
using namespace std;

namespace BHC{
	
    void bbulinkle(){
    	cout << " BHC 네임스페이스의 Bbulinkle() 함수" << endl;
    }
    
    void matchoking(){
    	cout << " BHC 네임스페이스의 matchoking() 함수" << endl;
    }
}

int main(void)
{
	BHC::bbulinkle();
    BHC::matchoking();
    
    //bbulinkle(); 불가능
    //matchoking(); 불가능
    
    using namespace BHC;
    //BHC 내부 요소에 BHC::없이 접근 가능
    
    bbulinkle(); //가능
    matchoking(); //가능
    
    return 0;
}   
 
//main과는 다른 함수
void example() {
    //bbulinkle(); 불가능
    //matchoking(); 불가능
	BHC::bbulinkle();
    BHC::matchoking();
}

 

지역변수다 생각하고 보면 이해하기 쉬울 것이다.

결국 번호만 붙였을 뿐 달라진 점은 함수를 전역적으로 사용할 수 있는가, 아니면 지정된 함수 내에서만 사용할 수 있는가에 대한 차이점만 존재할 뿐이다.

 

6️⃣전역 네임스페이스 접근 방법 (global namespace)

namespace에 속한 요소는 한정된 이름 접근 방법에 따라 "네임스페이스::요소"를 통해서 그 요소에만 접근이 가능하다.

 

전역에 있는 요소를 뙇 가리키려면 우째야할까?

 

"::요소 " 를 통해 글로벌 네임스페이스에 접근할 수 있다.

 

글로벌 네임스페이스에 접근한다 = 전역 변수를 사용한다

그럼 언제쓸까? using선언이나, using 지시어를 통해 동일 요소가 존재할 경우에 전역 요소를 확실히 구분하기 위해서 사용할 수 있다.

#include<iostream>
using namespace std;

namespace milk{
	void bananaflavor(){
    	cout << "milk 네임스페이스 bananaflavor() 함수 호출" << endl;
        }
}

using namespace milk; //using 지시어

void drive(){ cout << "글로벌 네임스페이스 bananaflavor() 함수 호출" << endl; }

int main(void)
{
	//bananaflavor(); 뭐가 뭔지 확인이 불가능하기 때문에 충돌이 발생해 사용 불가
    
    ::bananaflavor();     // 글로벌 
    milk::bananaflavor(); //milk 네임스페이스
    
    return 0;
}

 

using 지시어를 통해 milk 이름 공간의 요소를 제약 없이 접근 가능하도록 만들게 되면 bananaflavor()라는 함수 자체로 호출이 불가능해진다.

전역 bananaflavor()함수인지, milk::bananaflavor()함수인지 불명확 하기 때문

 

위와 같은 이유 때문에  글로벌 네임스페이스 bananflavor를 호출하려면 ::bananflavor()를 사용하며,

milk 네임스페이스 bananaflavor를 호출하려면 using지시어 선언을 했다해도 milk::bananaflavor()를 이용해야 하는 것이다.

 

이처럼 요소의 이름이 겹치게 되면 using 지시어, using 선언 접근이 무의미해지고, 결국 "네임스페이스이름::요소"의 한정된 이름 접근 방법을 사용해야 한다.

 

 

 

✅C++ 표준 std 네임스페이스


C++은 모든 표준 요소를 std 이름 공간에 만들어 둔다.

우리가 보통 사용하는 C++코드를 보면 파일 최 상단에 헤더 파일인 include를 작성 후 다음에

using namespace std;를 볼 수 있다.

 

C++의 표준 요소들은 보통 std라는 공간에 있기에 

cin/ cout등의 함수들을 using 없이 사용하면, std::cin, std::cout으로 사용해야 하는 것이다.

#include<iostream>
int main(void)
{
	std::cout << "출력" <<std:end1;
    return 0;
}

 

 

충돌을 피하고자 여러가지 방법이 있지만,

제일 확실한 방법은 "네임스페이스::요소"처럼 한정된 접근을 통해 namespace에 접근하는 것이 제일 좋다.

반응형

댓글