C ++에서 네임 스페이스를 어떻게 올바르게 사용합니까?


231

네임 스페이스가 아닌 패키지가 사용되는 Java 배경에서 왔습니다. 패키지로 완전한 객체를 형성하기 위해 함께 작동하는 클래스를 넣은 다음 나중에 해당 패키지에서 재사용하는 데 익숙합니다. 하지만 지금은 C ++에서 일하고 있습니다.

C ++에서 네임 스페이스를 어떻게 사용합니까? 전체 애플리케이션에 대해 단일 네임 스페이스를 작성합니까, 아니면 주요 구성 요소에 대한 네임 스페이스를 작성합니까? 그렇다면 다른 네임 스페이스의 클래스에서 객체를 어떻게 생성합니까?

답변:


167

네임 스페이스는 기본적으로 패키지입니다. 그들은 다음과 같이 사용될 수 있습니다 :

namespace MyNamespace
{
  class MyClass
  {
  };
}

그런 다음 코드에서 :

MyNamespace::MyClass* pClass = new MyNamespace::MyClass();

또는 항상 특정 네임 스페이스를 사용하려면 다음을 수행하십시오.

using namespace MyNamespace;

MyClass* pClass = new MyClass();

편집 : 무엇을 다음 bernhardrusch가 내 개체 (내가 보였다 즉 첫 번째 예제를) 인스턴스화 할 때 말했다, 나는 모든에서 "사용하여 네임 스페이스 X"구문을 사용하지 않는 경향이, 나는 보통 명시 적으로 네임 스페이스를 지정합니다.

아래 에 요청 한대로 원하는만큼 네임 스페이스를 사용할 수 있습니다.


25
IMO std네임 스페이스 접두사를 사용하는 대신 기호 로 접두사를 사용하는 것이 더 좋습니다 using. 난 항상 쓰기 그래서 std::coutstd::string지금 내가 지금 부르는 때문이다. 난 그냥 쓰지 않을 것 cout입니다.
Tom Savage

5
이것이 매우 사실이지만 std, 더 작은 라이브러리를 다룰 때 개인적으로 훨씬 덜 중요하다는 것을 알았습니다. 종종 당신은 사용할 수 있습니다 using namespace FooBario;당신이 라이브러리 유형의 상당한 번호를 사용하는 경우 특히.
jkerian

4
@ jkerian, 나는 당신의 요점을 알지만, 이름 충돌이 (내 마음에) 정확하게 작은 라이브러리에서 올 가능성이 높기 때문에 동의하지 않습니다. 대부분의 사람들은 클래스 / 함수를 STL과 동일하게 이름 지정하지 않도록주의합니다. 즉, using namespace X;가능한 경우 헤더 파일에서 피해야 한다는 데 동의 합니다.
Alan Turing

12
@LexFridman "대부분의 사람들은 클래스 / 함수를 STL과 동일하게 이름을 지정하지 않도록주의합니다"-그것은 참이 아닙니다. 예를 들어, 이상한 하드웨어에 대해 매우 전문화 된 I / O 코드를 작성한다면, mylibrary::endl나만의 특수 개행 시퀀스를 나타내는 것 외에는 다른 것을 사용하지 않을 것 입니다. 왜 이름을 발명합니까?

명시 적으로 지정하고 선언 된 파일을 포함하더라도 내 컴파일러는 여전히 네임 스페이스를 인식하지 못합니다.
bgenchel

116

모든 것을 말하지 않으려면 Mark Ingram은 이미 네임 스페이스 사용에 대한 작은 팁을 말했습니다.

헤더 파일에서 "네임 스페이스 사용"지시문을 피하십시오. 이렇게하면이 헤더 파일을 가져 오는 프로그램의 모든 부분에 대한 네임 스페이스가 열립니다. 구현 파일 (* .cpp)에서는 일반적으로 큰 문제가되지 않습니다. 함수 수준에서 "네임 스페이스 사용"지시문을 사용하는 것이 좋습니다.

네임 스페이스는 이름 충돌을 피하기 위해 주로 사용된다고 생각합니다. 코드 구조를 구성 할 필요는 없습니다. 헤더 파일 / 파일 구조로 주로 C ++ 프로그램을 구성했습니다.

때로는 더 큰 C ++ 프로젝트에서 네임 스페이스를 사용하여 구현 세부 사항을 숨길 수 있습니다.

using 지시문에 대한 추가 참고 사항 : 일부 사람들은 단일 요소에 대해서만 "using"을 사용하는 것을 선호합니다.

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

2
.cpp 내의 .cpp 파일 수준 또는 네임 스페이스 {} 블록 수준이 아니라 함수 수준에서 "네임 스페이스 사용"의 한 가지 이점은 단일 컴파일 단위 빌드에 크게 도움이된다는 것입니다. "네임 스페이스 사용"은 전 이적이며 동일한 단위의 개별 네임 스페이스 A {} 블록에 걸쳐 네임 스페이스 A에 적용되므로 단일 컴파일 단위 빌드의 경우 파일 또는 네임 스페이스 블록 수준에서 수행되는 경우 모든 것을 사용하여 빠르게 종료됩니다.
idij

using std::cout; 사용 선언입니다
Konstantin

3
단일 명령문에서 단일 네임 스페이스의 여러 이름 을 사용할 있습니까? , 또는 같은 것 . using std::cout, std::endl;using std::cout, endl;
AlQuemist

using namespace x다른 네임 스페이스 내에있는 경우 헤더 를 사용하는 것이 좋습니다. 일반적으로 권장하는 것은 아니지만 전역 네임 스페이스를 오염시키지 않습니다.
Praxeolitic 2016 년

79

Vincent Robert는 자신의 의견에 맞습니다 . C ++에서 네임 스페이스를 어떻게 올바르게 사용합니까? .

네임 스페이스 사용

네임 스페이스는 최소한 이름 충돌을 피하기 위해 사용됩니다. Java에서는 "org.domain"관용구를 통해 적용됩니다 (자체 도메인 이름 이외의 다른 것을 사용하지 않기 때문).

C ++에서는 모듈의 모든 코드에 네임 스페이스를 제공 할 수 있습니다. 예를 들어, MyModule.dll 모듈의 경우 해당 코드에 네임 스페이스 MyModule을 제공 할 수 있습니다. 다른 곳에서 MyCompany :: MyProject :: MyModule을 사용하는 사람을 보았습니다. 나는 이것이 과잉이라고 생각하지만 대체로 그것은 나에게 맞는 것 같습니다.

"사용"사용

네임 스페이스에서 현재 네임 스페이스로 하나 (또는 ​​모든) 심볼을 효과적으로 가져 오기 때문에 Using를 신중하게 사용해야합니다.

헤더는 헤더를 포함하여 모든 소스를 오염 시키므로 (매크로를 생각 나게합니다 ...) 소스 파일에서도 전역 범위에서 가져 오기 때문에 함수 범위 외부의 나쁜 스타일이기 때문에 헤더 파일에서 수행하는 것은 좋지 않습니다. 네임 스페이스의 심볼

"사용"을 사용하는 가장 안전한 방법은 선택 기호를 가져 오는 것입니다.

void doSomething()
{
   using std::string ; // string is now "imported", at least,
                       // until the end of the function
   string a("Hello World!") ;
   std::cout << a << std::endl ;
}

void doSomethingElse()
{
   using namespace std ; // everything from std is now "imported", at least,
                       // until the end of the function
   string a("Hello World!") ;
   cout << a << endl ;
}

"네임 스페이스 std 사용"이 많이 표시됩니다. 튜토리얼 또는 예제 코드에서. 그 이유는 좋은 생각이 아니기 때문에 더 쉽게 읽을 수 있도록 기호 수를 줄이는 것입니다.

"네임 스페이스 std 사용;" Scott Meyers는 권장하지 않습니다 (정확히 어떤 책을 기억하지 않지만 필요한 경우 찾을 수 있습니다).

네임 스페이스 구성

네임 스페이스는 단순한 패키지가 아닙니다. 다른 예제는 Bjarne Stroustrup의 "The C ++ Programming Language"에서 찾을 수 있습니다.

8.2.8 네임 스페이스 구성 의 "Special Edition"에서 두 개의 네임 스페이스 AAA 및 BBB를 CCC라는 다른 네임 스페이스로 병합하는 방법에 대해 설명합니다. 따라서 CCC는 AAA와 BBB의 별명이됩니다.

namespace AAA
{
   void doSomething() ;
}

namespace BBB
{
   void doSomethingElse() ;
}

namespace CCC
{
   using namespace AAA ;
   using namespace BBB ;
}

void doSomethingAgain()
{
   CCC::doSomething() ;
   CCC::doSomethingElse() ;
}

다른 네임 스페이스에서 선택 기호를 가져 와서 고유 한 네임 스페이스 인터페이스를 만들 수도 있습니다. 나는 아직 이것을 실제로 사용하지는 못했지만 이론 상으로는 시원하다.


"모듈의 모든 코드에 네임 스페이스를 지정하십시오"라고 설명 하시겠습니까? 모듈에 캡슐화하는 것이 좋습니다. 예를 들어 나는 복소수 클래스와 복소수와 관련된 외부 함수를 가지고 있습니다. 이 클래스와 그 두 함수는 하나의 네임 스페이스에 있어야합니까?
yanpas

74

나는 다른 답변에서 언급하지 않았으므로 여기 2 캐나다 센트가 있습니다.

"네임 스페이스 사용"주제에서 유용한 명령문은 네임 스페이스 별명으로, 네임 스페이스를 "이름 바꾸기"하여 일반적으로 더 짧은 이름을 지정할 수 있습니다. 예를 들어,

Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::TheClassName foo;
Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally::AnotherClassName bar;

당신은 쓸 수 있습니다:

namespace Shorter = Some::Impossibly::Annoyingly::Long:Name::For::Namespace::Finally;
Shorter::TheClassName foo;
Shorter::AnotherClassName bar;

55

네임 스페이스는 단지 네임 스페이스 일 뿐이라는 모든 사람들의 말을 듣지 마십시오.

인터페이스 원리를 적용하기 위해 컴파일러에서 고려하기 때문에 중요합니다. 기본적으로 예제로 설명 할 수 있습니다.

namespace ns {

class A
{
};

void print(A a)
{
}

}

A 객체를 인쇄하려면 코드는 다음과 같습니다.

ns::A a;
print(a);

함수를 호출 할 때 네임 스페이스를 명시 적으로 언급하지 않았습니다. 이것이 인터페이스 원리입니다. C ++는 유형을 해당 유형에 대한 인터페이스의 일부로 인수로 사용하는 함수를 고려하므로 매개 변수가 이미 네임 스페이스를 암시했기 때문에 네임 스페이스를 지정할 필요가 없습니다.

왜이 원리가 중요한가? 클래스 A 작성자가이 클래스에 대해 print () 함수를 제공하지 않았다고 가정하십시오. 직접 제공해야합니다. 훌륭한 프로그래머이므로이 함수를 고유 네임 스페이스 또는 글로벌 네임 스페이스에서 정의 할 수 있습니다.

namespace ns {

class A
{
};

}

void print(A a)
{
}

그리고 코드는 원하는 곳에서 print (a) 함수 호출을 시작할 수 있습니다. 몇 년 후, 저자는 클래스의 내부를 알고 당신보다 더 나은 버전을 만들 수 있기 때문에 당신보다 더 나은 print () 함수를 제공하기로 결정했다고 상상해보십시오.

그런 다음 C ++ 작성자는 인터페이스 원칙을 존중하기 위해 다른 네임 스페이스에 제공된 함수 대신 print () 함수 버전을 사용해야한다고 결정했습니다. 그리고 print () 함수의이 "업그레이드"는 가능한 한 쉬워야합니다. 즉, print () 함수에 대한 모든 호출을 변경할 필요가 없습니다. 이것이 C ++에서 네임 스페이스를 지정하지 않고 "인터페이스 함수"(클래스와 동일한 네임 스페이스의 함수)를 호출 할 수있는 이유입니다.

그렇기 때문에 C ++ 네임 스페이스를 "인터페이스"로 사용하고 인터페이스 원칙을 염두에 두어야합니다.

이 동작에 대한 더 나은 설명을 원한다면 Herb Sutter의 탁월한 C ++ 책을 참조하십시오.


23
ns :: Print가 추가 된 경우 실제로 print ()에 대한 모든 호출을 변경해야하지만 컴파일러는 각 호출을 모호한 것으로 플래그 지정합니다. 새로운 기능으로 자동 전환하는 것은 끔찍한 생각입니다.
Eclipse

autor이 ns :: Print () 함수를 제공한다면 @Vincent가 인쇄 할 모든 호출을 변경해야한다고 말한 것은 무엇입니까? 저자가 ns :: Print () 함수를 추가했을 때 자신의 구현을 제거 할 수 있습니까? 아니면 그냥 ns :: print () using-declaration을 사용하여 추가합니까? 아니면 다른 건가요? 감사합니다
Vaska el gato 2016

36

더 큰 C ++ 프로젝트 두 개 이상의 네임 스페이스 (예 : 부스트 라이브러리)를 거의 사용하지 않는 것을 보았습니다.

실제로 boost는 많은 네임 스페이스를 사용하며, 일반적으로 boost의 모든 부분에는 내부 작업을위한 고유 한 네임 스페이스가 있으며 최상위 네임 스페이스 boost에는 공용 인터페이스 만 배치 할 수 있습니다.

개인적으로 코드베이스가 클수록 단일 응용 프로그램 (또는 라이브러리) 내에서도 더 중요한 네임 스페이스가된다고 생각합니다. 직장에서 우리는 애플리케이션의 각 모듈을 자체 네임 스페이스에 넣습니다.

내가 많이 사용하는 네임 스페이스의 또 다른 용도는 말도 안되는 네임 스페이스입니다.

namespace {
  const int CONSTANT = 42;
}

이것은 기본적으로 다음과 같습니다.

static const int CONSTANT = 42;

그러나 정적 네임 스페이스 대신 정적 네임 스페이스를 사용하는 것이 C ++의 현재 컴파일 단위 내에서만 코드와 데이터를 볼 수있는 권장 방법입니다.


13
const int CONSTANT = 42;네임 스페이스 범위의 최상위 const는 이미 내부 연결을 의미하므로 두 예제는 모두 같습니다 . 따라서이 경우 익명 네임 스페이스가 필요하지 않습니다.
sellibitze

19

또한 네임 스페이스에 추가 할 수 있습니다. 이것은 예를 들어 더 명확합니다. 내가 의미하는 것은 다음을 가질 수 있다는 것입니다.

namespace MyNamespace
{
    double square(double x) { return x * x; }
}

파일 square.h에서

namespace MyNamespace
{
    double cube(double x) { return x * x * x; }
}

파일에 cube.h. 이는 단일 네임 스페이스를 정의합니다 MyNamespace(즉, 여러 파일에서 단일 네임 스페이스를 정의 할 수 있음).


11

자바에서 :

package somepackage;
class SomeClass {}

C ++에서 :

namespace somenamespace {
    class SomeClass {}
}

그리고 그것들을 사용하여 Java :

import somepackage;

그리고 C ++ :

using namespace somenamespace;

또한 전체 이름은 Java의 경우 "somepackge.SomeClass"이고 C ++의 경우 "somenamespace :: SomeClass"입니다. 이러한 규칙을 사용하면 네임 스페이스에 대해 일치하는 폴더 이름을 만드는 것을 비롯하여 Java에 익숙한 것처럼 구성 할 수 있습니다. 폴더-> 패키지 및 파일-> 클래스 요구 사항은 없으므로 패키지 및 네임 스페이스와 별도로 폴더와 클래스의 이름을 지정할 수 있습니다.


6

@ 마리우스

예, 한 번에 여러 네임 스페이스를 사용할 수 있습니다.

using namespace boost;   
using namespace std;  

shared_ptr<int> p(new int(1));   // shared_ptr belongs to boost   
cout << "cout belongs to std::" << endl;   // cout and endl are in std

[2 월. 2014-(정말로 오래 걸렸습니까?) :이 특정 예는 Joey가 아래에 지적한 것처럼 모호합니다. Boost와 std :: 이제 각각 shared_ptr을 갖습니다.]


2
참고 std또한이 shared_ptr지금, 그래서 모두를 사용 boost하고 std당신이를 사용하려고하면 네임 스페이스가 충돌합니다 shared_ptr.
Joey

2
이것은 많은 소프트웨어 하우스가 이러한 방식으로 전체 네임 스페이스를 가져 오는 것을 권장하지 않는 좋은 예입니다. 네임 스페이스를 항상 지정하는 것은 문제가되지 않습니다. 네임 스페이스가 너무 길면 네임 스페이스에서 별칭이나 중요한 특정 클래스 만 만드는 것이 좋습니다.
paddy

5

함수 안에 "using namespace ..."를 포함 할 수도 있습니다.

void test(const std::string& s) {
    using namespace std;
    cout << s;
}

3

일반적으로 함수 또는 형식 이름이 다른 라이브러리와 충돌 할 수 있다고 생각되면 코드 본문의 네임 스페이스를 만듭니다. 또한 브랜드 코드를 높이는 데 도움이됩니다 .


3

응용 프로그램에는 최상위 네임 스페이스를 사용하고 구성 요소에는 하위 네임 스페이스를 사용하는 것이 좋습니다.

다른 네임 스페이스의 클래스를 사용하는 방법은 놀랍게도 Java와 매우 유사합니다. "import PACKAGE"문과 유사한 "use NAMESPACE"를 사용할 수 있습니다 (예 : std 사용). 또는 패키지를 "::"으로 구분 된 클래스의 접두사로 지정합니다 (예 : std :: string). 이것은 Java의 "java.lang.String"과 유사합니다.


3

C ++의 네임 스페이스는 실제로 네임 스페이스 일뿐입니다. 패키지가 Java에서 수행하는 캡슐화를 제공하지 않으므로 많이 사용하지 않을 것입니다.


2

C ++, Perl 등에서와 같은 방식으로 C ++ 네임 스페이스를 사용했습니다. 표준 라이브러리, 타사 및 내 코드 간의 기호를 의미 적으로 분리 한 것입니다. 하나의 네임 스페이스에 내 자신의 앱을 배치 한 다음 분리를 위해 다른 네임 스페이스에 재사용 가능한 라이브러리 구성 요소를 배치합니다.


2

Java와 C ++의 또 다른 차이점은 C ++에서 네임 스페이스 계층 구조가 파일 시스템 레이아웃을 조작 할 필요가 없다는 것입니다. 따라서 재사용 가능한 전체 라이브러리를 단일 네임 스페이스에 넣고 라이브러리 내의 하위 시스템을 하위 디렉토리에 넣는 경향이 있습니다.

#include "lib/module1.h"
#include "lib/module2.h"

lib::class1 *v = new lib::class1();

이름이 충돌 할 가능성이있는 경우 서브 시스템을 중첩 된 네임 스페이스에만 배치합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.