2010-12-22 3 views
16

내부 링크를 정의하는 데 오랫동안 static 키워드를 사용했습니다. 나중에 익명의 네임 스페이스에서 로컬 객체를 래핑하는 C++ 스타일로 전환했습니다.익명의 네임 스페이스 : 정말 훌륭합니까?

그러나 익명의 네임 스페이스로 몇 년 동안 작업했을 때 나는 static 키워드로 작업하기가 훨씬 쉽다고 생각하기 시작했습니다.

일반적인 문제는이 패턴을 가지고있다 : 특정 기능은 내부 또는 외부 링크가있는 경우

namespace { 
    // ...five pages of code... 
} // namespace 

이전 C 스타일의 반대로 지금, 많이 스크롤해야 볼하려면를 어디 함수/객체 앞에 static이 있는지 확인할 수 있습니다.

익명의 네임 스페이스가 있습니다. static은 typedef를 숨길 수 없습니다.하지만 개인적으로는별로 관심이 없습니다.

당신의 책임은 무엇입니까? 익명의 네임 스페이스의 승리가 그로 인해 가독성이 떨어짐을 보증합니까? 아니면 내가 잘못 됐어?

+3

네임 스페이스 범위의'static' 함수는 더 이상 사용되지 않습니다. 사용하지 않는 충분한 이유가 있습니다. anon 네임 스페이스의 함수는 외부 링크가 있다는 점을 제외하면'static'의 모든 이점을 가지고 있습니다. 후자는 이미 익명의 네임 스페이스에 정의 된 이름을 내 보낸 섹션에서 제거하여 컴파일러가 처리했다고 생각합니다. –

+11

@Gene 실제로 정적 함수는 절대로 사용되지 않습니다. deprecation은 * objects *에 대해서만 사용되었습니다. 그러나 n3225에서는 deprecation이 제거되었습니다. C++ 0x에서는 객체 또는 함수에 내부 링크를 제공하기 위해 더 이상 사용되지 않습니다. 또 다른 차이점은 명명되지 않은 네임 스페이스가 외부 연결을 유지한다는 것입니다. 네임 스페이스 및 해당 내용은 C++ 0x에서 내부 연결을 갖게됩니다. 따라서 정적 방법과 네임 스페이스 간에는 더 이상 차이가없는 것처럼 보입니다. 단, 네임 스페이스 방식은 'namespace {int a; } int a;'. –

+0

@Johannes : C++ 0x는 내부 링크가있는 템플릿 매개 변수를 허용합니까, 아니면 큰 변화를 가져 왔습니까? –

답변

20

네임 스페이스의 코드가 너무 긴 경우,이 일을 당신을 막을 아무것도 없습니다 : C++ 03 이름없는 네임 스페이스를 사용의 실제 활용에

namespace { 
    int foo(char* x) { 
     return x[0] + x[1]; 
    } 
} 

namespace { 
    int bar(char *x, char *y) { 
     return foo(x) + foo(y); 
    } 
} 

는 내용이 외부 을 가지고 정확하게는 linkage (그러나 TU 밖에서는 볼 수 없기 때문에 여전히 보이지 않습니다.) 템플릿 매개 변수는 내부 연결을 가질 수 없습니다.

namespace { 
    int foo(const char* x) { 
     return x[0] + x[1]; 
    } 
} 

static int foo2(const char *x) { 
    return x[0] + x[1]; 
} 

template <int (*F)(const char*)> 
void baz(const char *p) { 
    F(p); 
} 

int main() { 
    baz<foo>("ab"); // OK 
    baz<foo2>("ab"); // not valid 
} 
+0

네,하지만 그게 정말로 좋은 일입니까? 더 많은 타이핑과 더 많은 괄호가 균형을 이룬다. –

+4

@kotlinksi : 글쎄, 당신은 단지 몇 가지 코드 스크린에서'namespace {} '를 한 번만 타이핑했기 때문에 가독성 문제라고 말했다. 이제는 한 번 이상 타이핑하는 것이 쓰기 가능성 문제라고 말하고 있습니다.내부 연결을 사용하여 함수를 사용하여 관리 할 수 ​​있다면'정적'을 사용할 수 있습니다. 어떤 이유로 든 외부 링키지를 가진 함수가 필요하다면, 정적 인 것의 이점이 무엇인지는 중요하지 않습니다. 왜냐하면 그것들을 가질 수 없기 때문입니다. –

+0

@kotlinksy : 또 다른 가능성은이 기능들만을위한 헤더 파일을 만드는 것이라고 생각합니다. 이름을 지정하면 이름이없는 네임 스페이스에 모든 내용이 있음을 알 수 있습니다. 그런 다음 해당 파일이있는 파일의 위치를 ​​알 수 있습니다. –

1

익명 네임 스페이스는 클래스 선언으로 전역 범위를 오염시키지 않는 유일한 방법입니다. .cpp 파일에 클래스를 정의 할 때 매우 유용합니다.

2

는 별도로 스티브에 의해 언급 된 매우 유효한 점에서 나는 정적 함수에 우수한 만들 익명의 네임 스페이스에서 다른 매우 중요한 측면을 참조하십시오 소재지, 리팩토링 및 정보를 숨기고의 용이성.

매우 특정한 헬퍼 함수를 ​​필요로하지만 클래스 멤버를 사용하지 않는 하나 또는 두 개의 클래스 함수가 ​​있다고 가정합니다. 로버트 C. 마틴 (함수는 작아야하고 잘 정의 된 목적을 수행해야 함)을 사용하면 커다란 함수가 작은 함수로 리팩토링 될 수 있음을 알 수 있습니다. 작은 함수는 처음에는 큰 함수로만 사용될 수 있습니다.

그래서 옵션을 무엇을 가지고 :이 입력 꽤 많은 잔인한 수 있습니다 수반

와 -하자가 - 그것을 직면

  1. 즉시 새로운 (아마도 개인) 클래스를 확인 모두 은 때때로 게으르거나 서두릅니다.

  2. 개인 정적 기능 또는 비 멤버 함수 생성 : 더 흐름을 방해가 될 수

    당신이 그것을 제대로 할 경우 모두 헤더 파일과 CPP 파일을 편집 수반, 그래서 아직도 조금 부담 필요 이상으로 코드를 생성하여 불필요하게 이 헤더 파일을 혼란스럽게 만들거나, 앞으로 선언이 필요하거나 헤더에 추가로 포함될 수도 있습니다.

  3. 익명 네임 스페이스 : -> 거기를 넣고 그것이 사용되는 클래스 메소드에 가까운이 함수를 작성

    당신은 멤버 액세스를 필요로 하나의 목적을 제공하지 않는 도우미 기능이 . 이것은 크게 나의 선호하는 것 : 그것은 빠르며 헤더 파일을 어지럽히 지 않습니다. 네임 스페이스에는이 cpp 이외의 다른 것에 의해 사용되지 않는다는 내용이 명시되어 있습니다. 친구가 사용하지 않으며 라이브러리 사용자는 그 존재를 알 수 없습니다. 당신은 거의 더 명확하지 않을 수 있으며, 종종이 패러다임은 출력을 수정 한 적은 수의 입력 매개 변수 인 클리너 기능 디자인으로 이어질 것입니다. 또한 기능 지역성이 있습니다 : 주전의 사용 직전에 정의하십시오. 이것은 단점이 될 수도 있지만 큰 클래스를 구현할 때 구현을 탐색 할 때 상당히 도움이된다. 또 다른 이점은 몇 가지 함수에 걸쳐 있지만 라이브러리 사용자에게는 정말 흥미로운 것은 아닙니다. 네임 스페이스에도 넣으십시오. 사용하는 기능과 동일하게 가장 좋습니다. 나중에 으로 바뀌면 다른 곳에서 상수와 함수가 필요하므로 전체를 클래스로 변환합니다. 이미 클래스가 깔끔하게 정리되어 있습니다.

면책 조항 : 많은 사람들은 제재목의 사용이 훨씬 더 깨끗하다고 ​​주장 할 수 있습니다. 이것은 단지 내 개인 의견입니다.