는 중첩 된 형태와 유형의 인스턴스가 같은 이름을 가지고 있다는 사실이 기술의 핵심 측면이 아니다. 캡슐화를 높이기 위해 인스턴스 함수에 액세스하기 위해 멤버 함수를 사용할 수도 있습니다 (네임 스페이스 한정자처럼 보이지는 않지만). 예를 들어, 당신이 준 예는 단점없이 다음과 같이 다시 작성할 수 있습니다 (물론, 어쩌면있다, 그러나 나는 순간에 하나를 찾을 수 없습니다) :
여기
struct A
{
struct Controls
{
//typedefs/data/functions
};
const Controls & getControls() { return controls_; }
private:
Controls controls_;
};
A a;
A::Controls::iterator = a.getControls().begin();
내가 memberspaces를 참조하는 방법입니다. 구성원 공간의 목표는 관련된 typedef와 메소드를 그룹화하기 위해 클래스의 이름 공간을 나누는 것입니다. 위의 Controls
클래스는 A
외부에서 정의 할 수 있지만 A
(각각 A
은 Controls
과 연결되어 있고 Controls
은 포함되어있는 객체의 뷰일뿐입니다))가 느끼는 "자연"이 A
의 멤버로 만들려면, 등) A
의 내부에 접근 할 필요가있는 경우 가능도 (A
로에게 친구를합니다.
그래서 기본적으로 우리가 둘러싸는 클래스 네임 스페이스를 오염하지 않고, 단일 개체에 하나 또는 여러 개의 뷰를 정의 할 수 memberspaces. 기사에서 언급 한 바와 같이 당신이 당신의 클래스의 객체를 반복하는 여러 가지 방법을 제공하려는 경우, 이것은 매우 흥미로운 일이 될 수 있습니다.
예를 들어, C++ 클래스를 나타내는 클래스를 작성한다고 가정 해 보겠습니다. Class라고 부르 자. 클래스에는 이름과 모든 기본 클래스 목록이 있습니다. 편의상, Class를 상속받은 모든 클래스 (파생 클래스)의 목록도 저장하도록하겠습니다. 그래서 그런 코드 것이다 : 이제
class Class
{
string name_;
list< shared_ptr<Class> > baseClasses_;
list< shared_ptr<Class> > derivedClasses_;
};
을, 나는 기본 클래스/파생 클래스 추가/제거하기 위해 일부 멤버 함수가 필요합니다
class Class
{
public:
void addBaseClass(shared_ptr<Class> base);
void removeBaseClass(shared_ptr<Class> base);
void addDerivedClass(shared_ptr<Class> derived);
void removeDerivedClass(shared_ptr<Class> derived);
private:
//... same as before
};
그리고 때때로을 나는 방법을 추가해야 할 수도 있습니다
class Class
{
public:
typedef list< shared_ptr<Class> >::const_iterator const_iterator;
const_iterator baseClassesBegin() const;
const_iterator baseClassesEnd() const;
const_iterator derivedClassesBegin() const;
const_iterator derivedClassesEnd() const;
//...same as before
};
우리가 아직 관리 할 다루고있는 이름의 양, 그러나 우리는 역 반복을 추가하려면 무엇을 : 기본 클래스와 파생 클래스를 반복 하는가? 파생 클래스를 저장할 기본 유형을 변경하면 어떻게됩니까? 그것은 또 다른 유형의 typedef를 추가 할 것이다. 게다가, 반복자를 시작하고 끝내기위한 접근 방식이 표준 명명법을 따르지 않는다는 것을 알았을 것입니다. 즉, 우리는 추가적인 노력없이 Boost.Range와 같은 일반적인 알고리즘을 사용할 수 없다는 것을 알았을 것입니다.
실제로 우리가 접두사/접미어를 사용하여 논리적으로 그룹화하는 멤버 함수 이름을 볼 때, 우리가 이제는 네임 스페이스가있는 것을 피하려고 노력하는 것은 명백합니다. 그러나 클래스에서 네임 스페이스를 사용할 수 없기 때문에 트릭을 사용해야합니다.
이제 구성원 공간을 사용하여 모든 기본 관련 및 파생 관련 정보를 자체 클래스에 캡슐화하여 관련된 데이터/작업을 함께 그룹화 할 수있을뿐만 아니라 코드 중복을 줄일 수 있습니다. 기본을 조작하기위한 코드 ,
이 예에서
Class c;
Class::DerivedClasses::const_iterator = c.derivedClasses.begin();
boost::algorithm::find(c.derivedClasses, & c);
...
, 중첩 된 클래스가 너무 Class
에 연결되지 않습니다
class Class
{
struct ClassesContainer
{
typedef list< shared_ptr<Class> > const_iterator;
ClassesContainer(list< shared_ptr<Class> > & classes)
: classes_(classes)
{}
const_iterator begin() const { return classes_.begin(); }
const_iterator end() const { return classes_.end(); }
void add(shared_ptr<Class> someClass) { classes_.push_back(someClass); }
void remove(shared_ptr<Class> someClass) { classes.erase(someClass); }
private:
list< shared_ptr<Class> > & classes_;
};
public:
typedef ClassesContainer BaseClasses;
typedef ClassesContainer DerivedClasses;
// public member for simplicity; could be accessible through a function
BaseClasses baseClasses; // constructed with baseClasses_
DerivedClasses derivedClasses; // constructed with derivedClasses_
// ... same as before
};
지금 내가 할 수있는 : 클래스와 파생 클래스는 우리가 단 한 번의 중첩 클래스를 사용할 수 있습니다, 동일 그래서 그것은 정의 될 수있다. utside, 그러나 당신은 더 강한 경계를 가진 예제를 발견 할 수 있습니다.
글쎄,이 긴 게시물 이후, 나는 정말로 당신의 질문에 대답하지 않았다는 것을 알았습니다 :). 따라서 실제로 코드에서 구성원 공간을 실제로 사용한 적이 없지만 응용 프로그램이 있다고 생각합니다.
필자는 라이브러리에 대한 Facade 클래스를 작성했을 때 한두 번 생각해 보았습니다.이 Facade는 단일 진입 점을 사용하여 라이브러리를 더 쉽게 사용할 수 있도록하기위한 것이었지만 결과적으로 여러 멤버 기능은 모두 관련되었지만 "관련성"의 정도가 다릅니다. 또한, 그것은 객체의 모음을 표현했기 때문에 "기능 지향적"멤버 함수 외에도 반복 관련 typedef와 멤버 함수가 포함되었습니다. 필자는 구성원 공간을 사용하여 클래스를 논리적 인 "부분 공간"으로 나누어보다 깨끗한 인터페이스로 간주했습니다. 왜 내가하지 않았는지 모르겠다.
모두! 불쾌한! 블레치! –