Je travaille actuellement sur un projet dans lequel j'aimerais définir une interface de 'collection' générique qui peut être implémentée de différentes manières. L'interface de collection doit spécifier que la collection a des méthodes qui retournent les itérateurs par valeur. L'utilisation de classes que les pointeurs wrap je suis venu avec ce qui suit (très simplifié):Hiérarchie des classes C++ pour la collection fournissant des itérateurs
Collection.h
class Collection
{
CollectionBase *d_base;
public:
Collection(CollectionBase *base);
Iterator begin() const;
};
inline Iterator Collection::begin() const
{
return d_base->begin();
}
CollectionBase.h
class CollectionBase
{
public:
virtual Iterator begin() const = 0;
virtual Iterator end() const = 0;
};
Iterator.h
class Iterator
{
IteratorBase *d_base;
public:
bool operator!=(Iterator const &other) const;
};
inline bool Iterator::operator!=(Iterator const &other) const
{
return d_base->operator!=(*other.d_base);
}
IteratorBase.h
class IteratorBase
{
public:
virtual bool operator!=(IteratorBase const &other) const = 0;
};
En utilisant cette conception, les différentes implémentations de la collection dérivent de CollectionBase
et peuvent retourner leurs itérateurs personnalisés en retournant un Iterator
qui enveloppe une mise en œuvre spécifique de IteratorBase
.
Tout va bien et dandy jusqu'ici. J'essaie actuellement de comprendre comment implémenter operator!=
cependant. Iterator
transmet l'appel à IteratorBase
, mais comment l'opérateur doit-il être implémenté? Une méthode simple serait de simplement transtyper la référence IteratorBase
au type approprié dans les implémentations de IteratorBase
, puis d'effectuer la comparaison spécifique pour l'implémentation de IteratorBase
. Cela suppose que vous jouerez bien et ne passerez pas deux types différents d'itérateurs.
Une autre façon serait d'effectuer un certain type de vérification de type qui vérifie si les itérateurs sont du même type. Je crois que cette vérification devra être faite au moment de l'exécution, et vu qu'il s'agit d'un itérateur, je préférerais ne pas effectuer de vérification du type d'exécution coûteuse en operator!=
.
Est-ce qu'il me manque des solutions plus belles ici? Peut-être y a-t-il de meilleures conceptions de classe alternatives (la conception actuelle est une adaptation de quelque chose que j'ai appris dans un cours de C++ que je prends)? Comment aborderiez-vous cela?
Editer: Pour tout le monde me pointant vers les conteneurs STL: Je suis au courant de leur existence. Cependant, je ne peux pas les utiliser dans tous les cas, car la quantité de données à traiter est souvent énorme. L'idée ici est de mettre en œuvre un conteneur simple qui utilise le disque comme stockage au lieu de la mémoire.
oh gawd ... C++ déjà * a * le concept de conteneurs et itérateurs. Si vous jouiez avec cela, vous seriez capable d'utiliser du code tiers! Ne réinventez pas la roue. Surtout pas quand votre roue va être buggy, inefficace et plus difficile à utiliser. – jalf
"un conteneur simple qui utilise le disque comme stockage" Nous avons déjà ces - ils sont appelés fichiers. Un itérateur n'est pas une interface si sensible à un fichier, mais si vous le souhaitez, la norme le prévoit également. –