Pergunta

Eu estou tentando aprender C ++ então me perdoe se esta questão demonstra uma falta de conhecimento básico, você vê, o fato é que eu tenho uma falta de conhecimento básico.

Eu quero alguma ajuda trabalhar fora como criar um iterador para uma classe que criei.

Eu tenho uma classe 'Forma', que tem um recipiente de pontos. Eu tenho uma classe 'pedaço' que faz referência a uma forma e define uma posição para o Shape. Peça não tem uma forma que apenas faz referência a um Shape.

Eu quero que ele parecer Piece é um recipiente de pontos que são os mesmos que os da forma que ela referências, mas com o deslocamento da posição da peça adicional.

Eu quero ser capaz para percorrer Pontos da peça como se peça foi um recipiente próprio. Eu fiz um pouco de leitura ao redor e não encontrei nada que me ajudou. Eu ficaria muito grato por qualquer ponteiros.

Foi útil?

Solução

Você deve usar Boost.Iterators. Ele contém uma série de modelos e conceitos para implementar novas iterators e adaptadores para iteradores existentes. Tenho escrito um artigo sobre este mesmo tema; é na revista ACCU Dezembro de 2008. Discute-se uma solução (IMO) elegante para exatamente o seu problema:. Expor coleções de membros de um objeto, usando Boost.Iterators

Se você quiser usar apenas o STL, o Josuttis livro tem um capítulo sobre a implementação de seu próprio iteradores STL.

Outras dicas

/ EDIT: Eu vejo, um próprio iterador é realmente necessário aqui (I descaracterizou a pergunta em primeiro lugar). Ainda assim, eu estou deixando o código abaixo posição, porque ele pode ser útil em circunstâncias semelhantes.


É um próprio iterator realmente necessário aqui? Talvez seja suficiente para encaminhar todas as definições necessárias para o recipiente que contém os pontos reais:

// Your class `Piece`
class Piece {
private:
    Shape m_shape;

public:

    typedef std::vector<Point>::iterator iterator;
    typedef std::vector<Point>::const_iterator const_iterator;

    iterator begin() { return m_shape.container.begin(); }

    const_iterator begin() const { return m_shape.container.begin(); }

    iterator end() { return m_shape.container.end(); }

    const_iterator end() const { return m_shape.const_container.end(); }
}

Este é supondo que você está usando um vector internamente, mas o tipo pode ser facilmente adaptado.

Designing um STL como Container personalizado é um excelente artigo que explica algumas das conceitos básicos de como um STL como classe contêiner pode ser projetado junto com a classe iterator para ele. Reverter iterator (pouco mais difícil) que é deixado como um exercício: -)

HTH,

Você pode ler este DDJ artigo

Basicamente, herdar de std :: iterator para obter a maior parte do trabalho feito para você.

Escrevendo iteradores personalizados em C ++ pode ser bastante detalhado e complexo de entender.

Desde que eu não poderia encontrar uma maneira mínima para escrever um personalizado iterador eu escrevi este cabeçalho modelo que ajuda poder. Por exemplo, para fazer a classe Piece iterable:

#include <iostream>
#include <vector>

#include "iterator_tpl.h"

struct Point {
  int x;
  int y;
  Point() {}
  Point(int x, int y) : x(x), y(y) {}
  Point operator+(Point other) const {
    other.x += x;
    other.y += y;
    return other;
  }
};

struct Shape {
  std::vector<Point> vec;
};

struct Piece {
  Shape& shape;
  Point offset;
  Piece(Shape& shape, int x, int y) : shape(shape), offset(x,y) {}

  struct it_state {
    int pos;
    inline void next(const Piece* ref) { ++pos; }
    inline void begin(const Piece* ref) { pos = 0; }
    inline void end(const Piece* ref) { pos = ref->shape.vec.size(); }
    inline Point get(Piece* ref) { return ref->offset + ref->shape.vec[pos]; }
    inline bool cmp(const it_state& s) const { return pos != s.pos; }
  };
  SETUP_ITERATORS(Piece, Point, it_state);
};

Em seguida, você seria capaz de usá-lo como um STL normal de Container:

int main() {
  Shape shape;
  shape.vec.emplace_back(1,2);
  shape.vec.emplace_back(2,3);
  shape.vec.emplace_back(3,4);

  Piece piece(shape, 1, 1);

  for (Point p : piece) {
    std::cout << p.x << " " << p.y << std::endl;
    // Output:
    // 2 3
    // 3 4
    // 4 5
  }

  return 0;
}

Ele também permite a adição de outros tipos de iteradores como const_iterator ou reverse_const_iterator.

Espero que ajude.

A solução para o seu problema não é a criação de seus próprios iteradores, mas o uso de contêineres e iteradores STL existentes. Armazenar os pontos em cada forma em um recipiente como vector.

class Shape {
    private:
    vector <Point> points;

O que você faz a partir de então depende do seu design. A melhor abordagem é para percorrer pontos em métodos dentro Shape.

for (vector <Point>::iterator i = points.begin(); i != points.end(); ++i)
    /* ... */

Se você precisa de pontos de acesso Forma fora (este poderia ser um sinal de um design deficiente) você pode criar nos métodos da forma que irá retornar as funções de acesso iterador para pontos (nesse caso também criar um typedef pública para o recipiente pontos ). Olhe para a resposta por Konrad Rudolph para detalhes desta abordagem.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top