문제

일부 오래된 코드를 리팩토링하는 동안 a) 멤버 데이터에 대해 작동하지 않거나 다른 멤버 함수를 호출하지 않고 b) 다른 곳에서 유용할 수 있기 때문에 실제로 정적이어야 하는 여러 공개 메서드를 제거했습니다.

이로 인해 '도우미' 기능을 함께 그룹화하는 가장 좋은 방법에 대해 생각하게 되었습니다.Java/C# 방식은 개인 생성자와 함께 정적 함수 클래스를 사용하는 것입니다. 예:

class Helper  
{  
private:  
  Helper() { }
public:  
  static int HelperFunc1();  
  static int HelperFunc2();  
};

그러나 C++이므로 네임스페이스를 사용할 수도 있습니다.

namespace Helper  
{  
  int HelperFunc1();  
  int HelperFunc2();  
}

대부분의 경우 저는 네임스페이스 접근 방식을 선호한다고 생각하지만 각 접근 방식의 장단점이 무엇인지 알고 싶었습니다.예를 들어 클래스 접근 방식을 사용하면 오버헤드가 발생합니까?

도움이 되었습니까?

해결책

오버헤드는 문제가 되지 않지만 네임스페이스에는 몇 가지 장점이 있습니다.

  • 다른 헤더에서 네임 스페이스를 다시 열고 컴파일 종속성을 낮게 유지하면서 더 논리적으로 그룹화 할 수 있습니다.
  • 이점에 네임 스페이스 별명을 사용할 수 있습니다 (디버그/릴리스, 플랫폼 특정 헬퍼, ....)

    예를 들어나는 다음과 같은 일을 해왔습니다.

    namespace LittleEndianHelper {
       void Function();
    }
    namespace BigEndianHelper {
       void Function();
    }
    
    #if powerpc
       namespace Helper = BigEndianHelper;
    #elif intel
       namespace Helper = LittleEndianHelper;
    #endif
    

다른 팁

사용할 수 있는 사례 class (또는 struct) 위에 namespace 유형이 필요한 경우입니다. 예를 들면 다음과 같습니다.

struct C {
  static int f() { return 33; }
};

namespace N {
  int f() { return 9; }
}

template<typename T>
int foo() {
  return T::f();
}

int main() {
  int ret = foo<C>();
//ret += foo<N>(); // compile error: N is a namespace
  return ret;
}

Pieter의 뛰어난 응답에 덧붙이자면, 네임스페이스의 또 다른 장점은 다른 곳의 네임스페이스에 넣은 선언 항목, 특히 구조체를 전달할 수 있다는 것입니다.

//Header a.h
// Lots of big header files, spreading throughout your code
class foo
{
  struct bar {/* ... */);
};

//header b.h
#include a.h // Required, no way around it, pulls in big headers
class b
{
  //...
  DoSomething(foo::bar);
};

그리고 네임스페이스를 사용하면...

//Header a.h
// Big header files
namespace foo
{
  struct bar {/* ... */);
}

//header b.h
// Avoid include, instead forward declare 
//  (can put forward declares in a _fwd.h file)
namespace foo
{
  struct bar;
}

class b
{
  //...
  // note that foo:bar must be passed by reference or pointer
  void DoSomething(const foo::bar & o);
};

Forward 선언은 수백 개의 소스 파일에 걸쳐 있는 프로젝트를 마친 후 작은 헤더 변경 후 컴파일 시간에 큰 차이를 만듭니다.

Paercebal에서 편집

열거형 오류로 인해 종료되도록 하기에는 답변이 너무 좋았습니다(댓글 참조).열거형(현재 C++에서는 지원되지 않고 C++0x에서만 전방 선언 가능)을 구조체로 대체했습니다.

네임스페이스 사용의 가장 큰 장점은 네임스페이스를 다시 열고 나중에 더 많은 항목을 추가할 수 있다는 것입니다. 클래스에서는 그렇게 할 수 없습니다.이는 느슨하게 결합된 도우미에 대해 이 접근 방식을 더 좋게 만듭니다(예를 들어 모든 STL이 ::std에 있는 것처럼 전체 라이브러리에 대한 도우미 네임스페이스를 가질 수 있습니다).

클래스의 가장 큰 장점은 클래스를 사용하여 클래스 내에 중첩할 수 있다는 것입니다. 클래스에 네임스페이스를 중첩할 수는 없습니다.이는 밀접하게 결합된 도우미에 대해 이 접근 방식을 더 좋게 만듭니다.

클래스와 네임스페이스에 추가 오버헤드가 발생하지 않습니다.

네임스페이스는 Koenig 조회의 추가적인 이점을 제공합니다.도우미 클래스를 사용하면 코드가 더 장황해질 수 있습니다. 일반적으로 호출에 도우미 클래스 이름을 포함해야 합니다.

네임스페이스의 또 다른 이점은 나중에 가독성이 좋다는 것입니다.클래스의 경우 나중에 특정 클래스가 객체를 생성하는 데 사용되지 않는다는 점을 상기시키기 위해 "도우미"와 같은 단어를 포함해야 합니다.

실제로는 둘 다 오버헤드가 없습니다.컴파일 후에는 사용되는 이름만 다릅니다.

내 답변의 일부를 복사/잘라내기/재작업했습니다. C++에서 네임스페이스를 어떻게 적절하게 사용합니까?.

"사용하다"를 사용하다

도우미 함수의 "접두사"를 반복하지 않으려면 "using"을 사용할 수 있습니다.예를 들어:

struct AAA
{
   void makeSomething() ;
} ;

namespace BBB
{
   void makeSomethingElse() ;
}

void willCompile()
{
   AAA::makeSomething() ;
   BBB::makeSomethingElse() ;
}

void willCompileAgain()
{
   using BBB ;

   makeSomethingElse() ; // This will call BBB::makeSomethingElse()
}

void WONT_COMPILE()
{
   using AAA ; // ERROR : Won't compile

   makeSomething() ; // ERROR : Won't compile
}

네임스페이스 구성

네임스페이스는 패키지 그 이상입니다.또 다른 예는 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() ;
}

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

나는 도우미 함수를 만들 때 익명 네임스페이스를 사용하는 경향이 있습니다.(일반적으로) 해당 모듈을 관리하는 모듈에서만 볼 수 있으므로 종속성을 제어하는 ​​좋은 방법입니다.

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