.cpp 파일에서 C ++ 네임 스페이스 메서드를 정의하는 올바른 방법


108

중복 일 가능성이 있지만 검색하기 쉽지는 않습니다.

다음과 같은 헤더가 주어집니다.

namespace ns1
{
 class MyClass
 {
  void method();
 };
}

method().cpp 파일에서 여러 가지 방법으로 정의 된 것을 보았습니다 .

버전 1 :

namespace ns1
{
 void MyClass::method()
 {
  ...
 }
}

버전 2 :

using namespace ns1;

void MyClass::method()
{
 ...
}

버전 3 :

void ns1::MyClass::method()
{
 ...
}

'올바른'방법이 있습니까? 모두 같은 의미가 아니라는 점에서 '잘못된'것이 있습니까?


대부분의 코드에서 일반적으로 세 번째 버전을 보지만 (왜 : D는 모르겠습니다) 두 번째 버전은 네임 스페이스가 도입 된 이유와는 반대입니다.
Mr. Anubis 2011

1
흥미로운 사실과 마찬가지로 Visual Assist 리팩토링 도구는 대상 파일에서 이미 사용중인 스타일에 따라 # 1 또는 # 3을 사용하여 코드를 생성 할 수 있습니다.
미스터 보이

답변:


51

버전 2는 명확하지 않고 이해하기 쉽지 않습니다. 어떤 네임 스페이스가 MyClass속 하는지 모르고 비논리적 이기 때문입니다 (같은 네임 스페이스에없는 클래스 함수?).

버전 1은 네임 스페이스에서 함수를 정의하고 있음을 보여주기 때문에 옳습니다.

버전 3은 또한 ::범위 확인 연산자를 사용 MyClass::method ()하여 네임 스페이스에서 참조 했기 때문에 옳습니다 ns1. 버전 3을 선호합니다.

네임 스페이스 (C ++)를 참조하십시오 . 이것이 가장 좋은 방법입니다.


22
# 2를 "잘못"이라고 부르는 것은 엄청난 과장입니다. 이 논리에 의해 모든 기호 이름은 잠재적으로 다른 범위에서 다른 기호 이름을 숨길 수 있기 때문에 "잘못된"것입니다.
tenfour 2011

비논리적입니다. 잘 컴파일되지만 (답에서 잘못 설명했습니다), 왜 네임 스페이스 외부에 함수를 정의하겠습니까? 독자를 혼란스럽게합니다. 또한 많은 네임 스페이스를 사용하는 경우 MyClass가 속한 네임 스페이스를 표시하지 않습니다. 버전 1 & 3은이 문제를 해결합니다. 결론적으로, 그것은 잘못된 것이 아니라 명확하지 않고 혼란 스럽습니다.
GILGAMESH 2011

3
나는 @PhoenicaMacia에 동의합니다. 사용하는 트릭은 끔찍하고 혼란을 일으킬 수 있습니다. 연산자를 자유 함수로 구현하는 클래스를 고려하십시오. 헤더 namespace N {struct X { void f(); }; X operator==( X const &, X const & ); }에서 이제는 using 문을 사용하여 cpp 파일 에서 멤버 함수를로 void X::f() {}정의 X operator==(X const&, X const&)할 수 있지만 정의하면 다른 연산자를 정의하게됩니다. 헤더에 정의되어 있습니다 (프리 기능에 대해 1 또는 3을 사용해야합니다).
David Rodríguez-dribeas

1
특히 나는 1을 선호하고 링크 된 기사의 예제는 첫 번째 예제가 1을 사용하는 것을 실제로 해결하지 못하고 두 번째 예제는 1과 3의 혼합을 사용합니다 (함수는 자격 으로 정의 되지만 외부 네임 스페이스 내부에 정의되어 있음)
David Rodríguez-dribeas

1
3 개 중 1)이 최고라고 말하고 싶지만 대부분의 IDE는 네임 스페이스 선언 내부에 모든 것을 들여 쓰는 다소 성가신 습관을 가지고 있으며 약간의 혼란을 더합니다.
locka

28

5 년 후 나는 이것을 언급 할 것이라고 생각했는데, 둘 다 멋지고 악하지 않다.

using ns1::MyClass;

void MyClass::method()
{
  // ...
}

3
이것이 최고의 답변입니다. 가장 깔끔해 보이며 의도 치 않게 네임 스페이스로 사물을 가져올 수있는 OP 버전 1과 의도하지 않게 사물을 전역 공간으로 가져올 수있는 2의 문제를 방지합니다.
ayane_m nov.

예, 이것은 명시 적으로 의도를 선언하면서 3보다 적은 타이핑의 훌륭한 조합입니다.
jb

14

버전 4 (아래)는 버전 1 (반사 정의의 간결함)과 버전 3 (최대한 명시 적)의 장점을 결합하기 때문에 사용하고 있습니다. 가장 큰 단점은 사람들이 그것에 익숙하지 않지만 내가 신경 쓰지 않는 대안보다 기술적으로 우월하다고 생각하기 때문입니다.

버전 4 : 네임 스페이스 별칭을 사용하여 전체 검증 사용 :

#include "my-header.hpp"
namespace OI = outer::inner;
void OI::Obj::method() {
    ...
}

내 세계에서는 모든 것이 명시 적으로 규정되어 있기 때문에 네임 스페이스 별칭을 자주 사용하고 있습니다. 그렇지 않은 경우 (예 : 변수 이름) 또는 알려진 사용자 지정 지점 (예 : 함수 템플릿의 swap ())이 아닌 경우입니다.


1
나는 논리가 결함이있는가 "이 사람들을 혼동하는 경우 난 상관 없어 그래서 더 낫다"생각하는 동안, 나는이 동의 할 것입니다 중첩 된 네임 스페이스를위한 좋은 방법.
Mr. Boy

1
"그것에 대해 생각하지 않은 이유"아이디어에 +1! ( "사람들은 [기술적으로 우수한 새로운 일들]에 익숙하지 않다"에 관해서는, 더 많은 사람들이 그것을한다면 익숙해 질 것입니다.)
wjl

그냥 확실히 내가 모두 이해 만들려면 outerinner이미 다른 헤더 파일에서 네임 스페이스로 정의?
dekuShrub

4

버전 3은 더 많은 타이핑 대신 클래스와 네임 스페이스 간의 연결을 매우 명시 적으로 만듭니다. 버전 1은 이것을 피하지만 블록과의 연관성을 캡처합니다. 버전 2는 이것을 숨기는 경향이 있으므로 피하고 싶습니다.



3

나는 Num.3 (일명 verbose 버전)을 선택합니다. 더 많은 타이핑이지만 의도는 당신과 컴파일러에게 정확합니다. 있는 그대로 게시 한 문제는 실제로 실제보다 간단합니다. 실제 세계에는 클래스 멤버뿐만 아니라 정의에 대한 다른 범위가 있습니다. 정의는 클래스만으로는 그리 복잡하지 않습니다. 왜냐하면 그 범위는 다시 열리지 않기 때문입니다 (네임 스페이스, 전역 범위 등과 달리).

Num.1 이것은 다시 열 수있는 클래스 이외의 범위에서 실패 할 수 있습니다. 따라서이 접근 방식을 사용하여 네임 스페이스에 새 함수를 선언하거나 인라인이 ODR을 통해 대체 될 수 있습니다. 일부 정의 (특히 템플릿 전문화)에이 정보가 필요합니다.

Num.2 이것은 특히 대규모 코드베이스에서 매우 취약합니다. 헤더와 종속성이 이동하면 프로그램이 컴파일되지 않습니다.

Num.3 이것은 이상적이지만 입력해야 할 것이 많습니다 . 무엇 을 정의하려는 의도입니다 . 이것은 정확히 그것을 수행하고 컴파일러는 실수하지 않았는지, 정의가 선언과 동기화되지 않았는지 등을 확인하기 위해 시작됩니다.



2

모든 방법이 옳으며 각 방법에는 장점과 단점이 있습니다.

버전 1에서는 각 함수 앞에 네임 스페이스를 작성할 필요가 없다는 장점이 있습니다. 단점은 특히 네임 스페이스 수준이 둘 이상인 경우 지루한 ID를 얻게된다는 것입니다.

버전 2에서는 코드를 더 깔끔하게 만들지 만 CPP에서 구현되는 네임 스페이스가 둘 이상인 경우 하나가 다른 하나의 함수와 변수에 직접 액세스하여 네임 스페이스를 쓸모 없게 만들 수 있습니다 (해당 cpp 파일에 대해).

버전 3에서는 더 많이 입력해야하고 기능 라인이 화면보다 클 수 있으므로 디자인 효과에 좋지 않습니다.

어떤 사람들이 그것을 사용하는 또 다른 방법이 있습니다. 첫 번째 버전과 유사하지만 식별 문제가 없습니다.

다음과 같습니다.

#define OPEN_NS1 namespace ns1 { 
#define CLOSE_NS1 }

OPEN_NS1

void MyClass::method()
{
...
}

CLOSE_NS1

각 상황에 대해 어느 것이 더 나은지 선택하는 것은 당신에게 달려 있습니다 =]


14
여기서 매크로를 사용할 이유가 없습니다. 들여 쓰기를 원하지 않으면 들여 쓰지 마십시오. 매크로를 사용하면 코드가 덜 명확 해집니다.
tenfour 2011

1
언급 한 마지막 버전은 네임 스페이스를 지원하지 않는 오래된 컴파일러로 코드를 컴파일 할 때 유용하다고 생각합니다 (예, 일부 공룡은 아직 주변에 있습니다). 이 경우 매크로를 #ifdef절 안에 넣을 수 있습니다 .
Luca Martini

원하지 않는 경우 식별 할 필요는 없지만 매크로를 사용하지 않는 경우 일부 IDE에서이를 수행합니다. 예를 들어 Visual Studio에서 전체 코드를 선택하고 Alt + F8을 눌러 자동 식별 할 수 있습니다. 정의를 사용하지 않으면 해당 기능을 잃게됩니다. 또한 OPEN_ (네임 스페이스) 및 CLOSE_ (네임 스페이스)가 코딩 표준에 포함되어 있다면 덜 명확하다고 생각하지 않습니다. @LucaMartini가 준 이유도 흥미 롭습니다.
Renan Greinert 2011

이것이 일반적으로 만들어 졌다면, 즉 약간 유용 #define OPEN_NS(X)하다고 생각 하지만 실제로는 아닙니다. 매크로에 반대하지는 않지만 이것은 약간 OTT 인 것 같습니다. 나는 Dietmar Kühl의 접근 방식이 중첩 된 네임 스페이스에 더 좋다고 생각합니다.
Mr. Boy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.