문제

멤버로서 std :: set을 가진 입자라는 클래스가 있습니다. 수업은 다음과 같습니다.

class Particle {
private:
    std::set<vtkIdType> cells;
    std::set<vtkIdType>::iterator ipc;

public:

    Particle() {};

    enum state {EXISTS = -1, SUCCESS = 0, ERROR = 1};

    state addCell(const vtkIdType cell);

    int numCells() { return static_cast<int>(cells.size()); }

    vtkIdType getFirstCell() { return (*(ipc = this->cells.begin()));}
    vtkIdType getNextCell() { return *(++ipc); }
    vtkIdType hasNextCell() { ++ipc; if (ipc == this->cells.end()) return false; --ipc; return true; }

    std::string getOutput();
};

나는 매우 불만족합니다 getFirstCell(), getNextCell() 특히 hasNextCell(), 나는 세트 자체를 노출시키고 싶지 않기 때문에 존재합니다. 나는 길을 사용해야했다 ++ipc 그리고 --ipc 왜냐하면 if((ipc+1) == this->cells.end()) 컴파일러 오류가 발생하면 IPC+1이 문제인 것 같습니다.

세트를 캡슐화하고 액세스하는 좋은 방법은 무엇입니까? 또한, 제거하는 좋은 방법이 있습니까? getFirstCell() 기능?

미리 감사드립니다.

편집 : 내가 게시 한 코드는 클래스 구조의 예일뿐입니다. "실제"클래스에는 더 많은 세트 와이 질문에 그다지 중요하지 않은 기타 데이터가 포함되어 있습니다 (나는 가정).

도움이 되었습니까?

해결책

왜 세트 자체를 노출시키고 싶지 않은지 잘 모르겠지만, 세트의 내용을 외부로 변경할 수 없도록하기 때문입니다. class Particle 그냥 돌아 오세요 const 세트를 "읽기 전용"으로 만드는 반복자, 예를 들어

typedef std::set<vtkIdType>::const_iterator CellIterator;
CellIterator beginCell() const { return this->cells.begin(); }
CellIterator endCell() const { return this->cells.end(); }

다른 팁

그 이유 ipc+1 작동하지 않습니다 std::set 지원하는 양방향 반복자 만 지원합니다 operator++ 그리고 operator--; 사용하기 위해 operator+, 무작위 액세스 반복기를 사용해야합니다.

내가 당신의 디자인에 대해 보는 한 가지 관심사는 당신의 기능이 액세서 (getsuchandsuch)와 같은 이름을 지어 지지만 객체의 내부 상태를 수정한다는 것입니다.ipc 수정). 이것은 혼란을 초래할 수 있습니다.

시도 할 수있는 한 가지는 반복자 (A를 반환하는 몇 가지 멤버 기능을 사용하는 것입니다. begin 그리고 end, 예를 들어), 클래스 사용자가 반복자를 사용하여 내부 세트에 액세스하고 여전히 세트 구현을 캡슐화 할 수 있도록합니다.

세트의 반복자 유형을 반환 할 수 있거나 더 많은 컨트롤 또는 캡슐화를 원한다면 세트의 반복기를 감싸는 고유 한 반복자 클래스를 구현할 수 있습니다.

SET :: ITERATOR (필요한 것보다 더 많은 것을 약속하지 않기 위해) 노출을 방지하려면 래퍼를 만들 수 있습니다.

class Particle::iterator
{
public:
  iterator()
  {}
  iterator &operator++()
  {
    ++InternalIterator;
    return *this;
  }
  vtkIdType &operator*() const
  {
    return *InternalIterator;
  }
  ...//other functionality required by your iterator's contract in the same way
private:
  iterator(const std::set<vtkIdType> &internalIterator)
    :InternalIterator(internalIterator)
  {}
  std::set<vtkIdType>::iterator InternalIterator;
};

Particle::iterator Particle::GetBeginCell()
{
  return iterator(cells.begin());
}
Particle::iterator Particle::GetEndCell()
{
  return iterator(cells.end());
}

따라서 내부 반복기를 제거 할 수 있으며 (하나의 반복기 만 갖는 것이 제한적이기 때문에) Particle Iterator의 STL에서 알고리즘을 사용할 수 있습니다.

또한 부스트 :: iterator_facade가 여기에서 유용 할 수 있습니다 ...

문제는 실제로 여기서 달성하려는 것입니다. 지금, 당신의 수업은 (적어도 나에게) 선보다 더 많은 해를 끼치는 것처럼 보입니다. 그것은 세트의 내용을 더 쉽게 어렵게 만듭니다.

나는 입자를보고 그것이 많은 세포를 저장/접근하는 방법을 넘어 의미있는 것을 제공 할 수 있는지 알아냅니다. 실제로 단순한 컨테이너라면, 당신은 같은 것을 훨씬 더 잘할 것입니다. typedef std::set<cell> Particle;, 따라서 최종 사용자는이 세트에서 다른 세트와 마찬가지로 알고리즘 등을 사용할 수 있습니다. 나는 당신이 의미있는 것을 실제로 캡슐화 할 수 있다면 - 즉 Particle 클래스는 입자에 대한 "지식"을 구현할 수 있으므로 다른 코드는 그 자체로 의미있는 것으로 입자와 함께 작동 할 수 있습니다.

지금, 당신의 Particle 컨테이너 일 뿐이며 특히 좋은 컨테이너처럼 보이지 않습니다. 실제로 무언가를 추가 할 수 없다면 이미있는 것을 사용하는 것이 더 나을 수 있습니다.

당신이 보여주는 것은 세 개의 getters 외에 아무것도하지 않습니다. 이 getters를 입자 클래스의 일부로 사용하는 작업을 수행하여 세트를 캡슐화하면 Getters가 필요하지 않습니다 : Voila, 캡슐화.

이미 보유한 일반 구현을 유지하려면 간단히 제거하십시오. getFirstCell(), 생성자 내에서 IPC를 초기화 할 수 있습니다. 위에서 언급 한 바와 같이, 신중한 사용 const 접근자와 돌연변이 체 사이의 명확한 차별화는 인터페이스를 명확하게 할 것이다. 또한, 수업에서 반복자를 구현하려면 addcell() 새 셀을 참조하는 반복자를 반환하고 대신 오류가 발생하면 예외를 던집니다.

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