관련 함수 집합이 있거나 작성하려고한다고 가정하겠습니다. 그들이 수학과 관련이 있다고 가정 해 봅시다. 조직적으로, 나는 :
- 이 함수를 작성하여
MyMath
네임 스페이스에 넣고 다음을 통해 참조하십시오.MyMath::XYZ()
- 호출 된 클래스를 만들고이
MyMath
메소드를 정적으로 만들고 유사하게 참조하십시오.MyMath::XYZ()
소프트웨어를 구성하는 수단으로 왜 다른 것을 선택해야합니까?
관련 함수 집합이 있거나 작성하려고한다고 가정하겠습니다. 그들이 수학과 관련이 있다고 가정 해 봅시다. 조직적으로, 나는 :
MyMath
네임 스페이스에 넣고 다음을 통해 참조하십시오.MyMath::XYZ()
MyMath
메소드를 정적으로 만들고 유사하게 참조하십시오.MyMath::XYZ()
소프트웨어를 구성하는 수단으로 왜 다른 것을 선택해야합니까?
답변:
기본적으로 네임 스페이스 함수를 사용하십시오.
클래스는 네임 스페이스를 대체하지 않고 객체를 빌드하는 것입니다.
Scott Meyers는이 주제에 대한 "유효한 C ++ 책에 대한 전체 항목"을 작성했습니다. Herb Sutter의 기사 에서이 원칙에 대한 온라인 참조를 찾았습니다.http://www.gotw.ca/gotw/084.htm
알아야 할 중요한 사항은 다음과 같습니다 . 클래스와 동일한 네임 스페이스의 C ++ 함수에서 ADL 은 함수 호출을 해결할 때 해당 함수를 검색 하기 때문에 해당 클래스의 인터페이스에 속합니다 .
네임 스페이스 함수는 "friend"로 선언되지 않으면 클래스의 내부에 액세스 할 수 없지만 정적 메서드는 사용할 수 있습니다.
예를 들어 클래스를 유지 관리 할 때 클래스의 내부를 변경해야하는 경우 정적 메서드를 포함한 모든 메서드에서 부작용을 검색해야합니다.
클래스 인터페이스에 코드 추가
C #에서는 액세스 권한이 없어도 클래스에 메서드를 추가 할 수 있습니다. 그러나 C ++에서는 불가능합니다.
그러나 여전히 C ++에서는 다른 사람이 작성한 클래스에도 네임 스페이스 함수를 추가 할 수 있습니다.
다른 측면에서 볼 때 이것은 코드를 디자인 할 때 중요합니다. 함수를 네임 스페이스에 배치하면 사용자가 클래스의 인터페이스를 늘리거나 완성 할 수있는 권한을 부여하기 때문입니다.
이전 포인트의 부작용으로 여러 헤더에 정적 메소드를 선언 할 수 없습니다. 모든 메소드는 동일한 클래스에서 선언되어야합니다.
네임 스페이스의 경우 동일한 네임 스페이스의 함수를 여러 헤더에 선언 할 수 있습니다 (가장 표준 스왑 함수가 그 중 가장 좋은 예입니다).
네임 스페이스의 기본 멋진 점은 일부 코드에서 "using"키워드를 사용하면 언급하지 않아도된다는 것입니다.
#include <string>
#include <vector>
// Etc.
{
using namespace std ;
// Now, everything from std is accessible without qualification
string s ; // Ok
vector v ; // Ok
}
string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR
"오염"을 한 클래스로 제한 할 수도 있습니다.
#include <string>
#include <vector>
{
using std::string ;
string s ; // Ok
vector v ; // COMPILATION ERROR
}
string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR
이 "패턴"은 거의 표준 스왑 관용구를 올바르게 사용하기 위해 필수적입니다.
그리고 이것은 클래스의 정적 메소드로는 불가능합니다.
따라서 C ++ 네임 스페이스에는 고유 한 의미가 있습니다.
그러나 상속과 비슷한 방식으로 네임 스페이스를 결합 할 수 있으므로 더욱 발전합니다.
예를 들어 함수 AAA가 포함 된 네임 스페이스 A, 함수 BBB가 포함 된 네임 스페이스 B가있는 경우 네임 스페이스 C를 선언하고 using을 키워드로이 네임 스페이스에 AAA 및 BBB를 가져올 수 있습니다.
네임 스페이스는 네임 스페이스를위한 것입니다. 수업은 수업을위한 것입니다.
C ++는 각 개념이 다르도록 서로 다른 문제에 대한 솔루션으로 다르게 사용되도록 설계되었습니다.
네임 스페이스가 필요할 때 클래스를 사용하지 마십시오.
그리고 귀하의 경우 네임 스페이스가 필요합니다.
나와 동의하지 않는 사람들이 많이 있지만 이것이 내가 보는 방식입니다.
클래스는 본질적으로 특정 종류의 객체에 대한 정의입니다. 정적 메소드는 해당 오브젝트 정의와 밀접하게 연관된 조작을 정의해야합니다.
기본 객체와 관련이없는 관련 함수 그룹 이나 객체 종류의 정의를 얻으 려면 네임 스페이스 만 사용한다고 말하고 싶습니다. 개념 상으로는이게 훨씬 더 합리적입니다.
예를 들어, 귀하의 경우, "MyMath 란 무엇입니까?" 경우 MyMath
객체의 종류를 정의하지 않습니다, 그때 내가 말할 것이다 : 그것은 클래스하지 않습니다.
그러나 내가 말했듯이, (특히 Java 및 C # 개발자)에 대해 (심지어) 나에게 동의하지 않을 사람들이 많이 있다는 것을 알고 있습니다.
typedef
있습니다 . 여러분은 그것들을 템플릿 매개 변수로 사용할 수 있습니다.
그렇지 않으면 네임 스페이스 함수를 사용하십시오.
주석에 대한 응답으로 예, 정적 메소드 및 정적 데이터가 과도하게 사용되는 경향이 있습니다. 그렇기 때문에 도움이 될만한 두 가지 관련 시나리오 만 제공했습니다 . OP의 특정 예제 (수학 루틴 세트)에서 모든 루틴에 적용되는 매개 변수 (예 : 핵심 데이터 유형 및 출력 정밀도)를 지정하는 기능을 원하는 경우 다음과 같은 작업을 수행 할 수 있습니다.
template<typename T, int decimalPlaces>
class MyMath
{
// routines operate on datatype T, preserving at least decimalPlaces precision
};
// math routines for manufacturing calculations
typedef MyMath<double, 4> CAMMath;
// math routines for on-screen displays
typedef MyMath<float, 2> PreviewMath;
그런 다음, 그 필요하지 않은 경우 모든 수단 네임 스페이스를 사용합니다.
template
주장 을 피하기 위해 클래스를 속기로 사용하십시오 !
네임 스페이스는 클래스에 비해 많은 장점이 있으므로 네임 스페이스를 사용해야합니다.
using
반원 이 될 수 없습니다 ; using
네임 스페이스 멤버 일 수 있습니다using class
, using namespace
종종 좋은 생각은 아닙니다.제 생각에 정적 멤버는 매우 과도하게 사용됩니다. 대부분의 경우에 꼭 필요한 것은 아닙니다. 정적 멤버 함수는 아마도 파일 범위 함수로 더 나을 수 있으며 정적 데이터 멤버는 더 나은 가치가있는 글로벌 객체 일뿐입니다.
inline
키워드를 사용하여 ODR을 충족하십시오.
inline
함수 본문을 "인라인"하지 않습니다. 의 실제 (그리고 표준에 의해 보장 된) 목적은 inline
다중 정의를 방지하는 것입니다. C ++의 "하나의 정의 규칙"에 대해 읽으십시오. 또한 ODR 문제 대신 미리 컴파일 된 헤더 문제로 인해 연결된 SO 질문이 컴파일되지 않았습니다.
구현 파일의 익명 네임 스페이스에 개인 데이터를 가질 수있는 네임 스페이스를 선호합니다 (따라서 private
멤버 와 달리 헤더에 전혀 표시 할 필요가 없습니다 ). 또 다른 이점은 using
네임 스페이스에서 메소드의 클라이언트가 지정을 거부 할 수 있다는 것입니다MyMath::
클래스를 사용해야하는 또 하나의 이유-액세스 지정자를 사용하는 옵션입니다. 그런 다음 공개 정적 메소드를 더 작은 개인 메소드로 나눌 수 있습니다. 공용 메소드는 여러 개인 메소드를 호출 할 수 있습니다.
private
방법 조차도 프로토 타입이 헤더에 전혀 게시되지 않아서 보이지 않는 방법보다 접근하기 쉽습니다. 익명의 네임 스페이스 기능으로 제공되는 더 나은 캡슐화에 대해서는 언급하지 않았습니다.
.cpp
파일 의 이름없는 네임 스페이스 안에이 정보를 숨길 수 있으므로 헤더 파일을 읽는 사람에게 불필요한 정보를 제공하지 않고도 해당 번역 단위에 비공개로 만들 수 있습니다. 효과적으로, 나는 PIMPL 관용구를 옹호하려고합니다.
.cpp
템플릿을 사용하려면 파일에 넣을 수 없습니다 .
네임 스페이스와 클래스 메서드는 모두 용도가 있습니다. 네임 스페이스는 여러 파일로 분산 될 수 있지만 모든 관련 코드를 한 파일로 강제로 적용해야하는 경우에는 약합니다. 위에서 언급했듯이 클래스를 사용하면 클래스에서 개인 정적 멤버를 만들 수도 있습니다. 구현 파일의 익명 네임 스페이스에 사용할 수 있지만 클래스 내부에있는 것보다 여전히 더 큰 범위입니다.
private:
입니다. 많은 경우에 특권 액세스 가 필요한 것처럼 보일 수 있습니다. 가장 '비공개'기능은 헤더에 나타나지 않는 기능입니다. private:
메소드는이 이점을 결코 누릴 수 없습니다.