Permitir la iteración sin filtrar las partes internas es exactamente lo que promete el patrón iterador. Por supuesto, eso es principalmente teoría, así que aquí hay un ejemplo práctico:
class AddressBook
{
using peoples_t = std::vector<People>;
public:
using iterator = peoples_t::iterator;
using const_iterator = peoples_t::const_iterator;
AddressBook();
iterator begin() { return people.begin(); }
iterator end() { return people.end(); }
const_iterator begin() const { return people.begin(); }
const_iterator end() const { return people.end(); }
const_iterator cbegin() const { return people.cbegin(); }
const_iterator cend() const { return people.cend(); }
private:
peoples_t people;
};
Usted proporciona estándares begin
y end
métodos, al igual que las secuencias en el STL, y los implementa simplemente reenviando al método vectorial Esto filtra algunos detalles de implementación, es decir, que está devolviendo un iterador de vectores, pero ningún cliente sensato debería depender de eso, por lo que no es una preocupación. He mostrado todas las sobrecargas aquí, pero por supuesto, puede comenzar simplemente proporcionando la versión constante si los clientes no pueden cambiar ninguna entrada de Personas. El uso de la nomenclatura estándar tiene beneficios: cualquiera que lea el código inmediatamente sabe que proporciona una iteración 'estándar' y, como tal, funciona con todos los algoritmos comunes, rango basado en bucles, etc.
begin()
yend()
son peligrosos porque (1) esos tipos son iteradores de vectores (clases) que evitan que uno cambie a otro contenedor como aset
. (2) Si se modifica el vector (p. Ej., Crecido o algunos elementos borrados), algunos o todos los iteradores del vector podrían haberse invalidado.