문제

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

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

도움이 되었습니까?

해결책

네임스페이스는 본질적으로 패키지입니다.다음과 같이 사용할 수 있습니다.

namespace MyNamespace
{
  class MyClass
  {
  };
}

그런 다음 코드에서:

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

도움이 되길 바랍니다.

또는 항상 특정 네임스페이스를 사용하려는 경우 다음을 수행할 수 있습니다.

using namespace MyNamespace;

MyClass* pClass = new MyClass();

편집하다: 무엇을 따라 베른하르트루쉬 저는 "using 네임스페이스 x" 구문을 전혀 사용하지 않는 경향이 있다고 말했습니다. 저는 일반적으로 객체를 인스턴스화할 때 네임스페이스를 명시적으로 지정합니다(예:내가 보여준 첫 번째 예).

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

다른 팁

Mark Ingram이 이미 말한 네임스페이스 사용에 대한 작은 팁을 모두 언급하지 않으려면 다음을 수행하세요.

헤더 파일에서 "using 네임스페이스" 지시어를 사용하지 마세요. 이렇게 하면 이 헤더 파일을 가져오는 프로그램의 모든 부분에 대한 네임스페이스가 열립니다.구현 파일(*.cpp)에서는 일반적으로 큰 문제가 되지 않습니다. 비록 함수 수준에서 "using 네임스페이스" 지시어를 사용하는 것을 선호하지만 말입니다.

내 생각에 네임스페이스는 대부분 이름 충돌을 피하기 위해 사용되는 것이지 반드시 코드 구조를 구성하기 위해 사용되는 것은 아닙니다.나는 주로 헤더 파일/파일 구조를 사용하여 C++ 프로그램을 구성했습니다.

때때로 네임스페이스는 구현 세부 사항을 숨기기 위해 더 큰 C++ 프로젝트에서 사용됩니다.

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

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

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++ 프로그래밍 언어"에서 찾을 수 있습니다.

"스페셜 에디션"에서는 8.2.8 네임스페이스 구성, 에서 그는 두 개의 네임스페이스 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() ;
}

다양한 네임스페이스에서 선택한 기호를 가져와서 자신만의 사용자 정의 네임스페이스 인터페이스를 구축할 수도 있습니다.나는 아직 이것의 실제적인 용도를 찾지 못했지만 이론적으로는 멋지다.

다른 답변에서는 이에 대한 언급을 보지 못했으므로 여기에 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;

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

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

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++ 네임스페이스를 사용할 때 C++ 네임스페이스를 "인터페이스"로 간주하고 인터페이스 원칙을 염두에 두어야 하는 이유입니다.

이 동작에 대한 더 나은 설명을 원하면 책을 참조할 수 있습니다. Herb Sutter의 뛰어난 C++

더 큰 C++ 프로젝트에서는 네임스페이스를 두 개 이상 사용하는 경우가 거의 없습니다(예:부스트 라이브러리).

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

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

제가 많이 사용하는 네임스페이스의 또 다른 용도는 익명 네임스페이스입니다.

namespace {
  const int CONSTANT = 42;
}

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

static const int CONSTANT = 42;

그러나 (정적 대신) 익명 네임스페이스를 사용하는 것은 코드와 데이터가 C++의 현재 컴파일 단위 내에서만 표시되도록 권장되는 방법입니다.

또한 네임스페이스에 추가할 수도 있습니다.예를 들어 보면 이것이 더 명확해집니다. 즉, 다음을 가질 수 있다는 것입니다.

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

파일에 square.h, 그리고

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

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

자바에서는:

package somepackage;
class SomeClass {}

C++에서:

namespace somenamespace {
    class SomeClass {}
}

그리고 이를 사용하여 Java는 다음을 수행합니다.

import somepackage;

그리고 C++:

using namespace somenamespace;

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

예를 들어 함수 내에 "using 네임스페이스 ..."를 포함할 수도 있습니다.

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

@마리우스

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

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가 아래에서 지적한 것처럼 이 특별한 예는 이제 모호합니다.부스트 및 표준::이제 각각은 shared_ptr을 갖습니다.]

일반적으로 다른 라이브러리와 함수 또는 유형 이름 충돌이 있을 수 있다고 생각되면 코드 본문에 대한 네임스페이스를 만듭니다.브랜드 코드에도 도움이 됩니다. 후원:: .

나는 애플리케이션에는 최상위 네임스페이스를 사용하고 구성 요소에는 하위 네임스페이스를 사용하는 것을 선호합니다.

다른 네임스페이스의 클래스를 사용하는 방식은 놀랍게도 Java의 방식과 매우 유사합니다."import PACKAGE" 문과 유사한 "use NAMESPACE"를 사용할 수 있습니다.표준을 사용하십시오.또는 "::"으로 구분된 클래스의 접두사로 패키지를 지정합니다.표준::문자열.이는 Java의 "java.lang.String"과 유사합니다.

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

저는 C#, Perl 등에서와 동일한 방식으로 C++ 네임스페이스를 사용했습니다.이는 표준 라이브러리 항목, 타사 항목 및 내 코드 간의 기호를 의미론적으로 분리한 것일 뿐입니다.내 앱을 하나의 네임스페이스에 배치한 다음 재사용 가능한 라이브러리 구성 요소를 다른 네임스페이스에 배치하여 분리했습니다.

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

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

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

이름이 충돌할 가능성이 있는 경우에만 하위 시스템을 중첩된 네임스페이스에 넣습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top