Comment faire pour chaque boucle de la fonction en C++ de travail avec une classe personnalisée
Je suis nouveau à la programmation C/C++, mais j'ai été à la programmation en C# pour 1,5 ans. J'aime le C# et j'aime aussi la Liste de classe, donc j'ai pensé à faire une Liste de classe en C++ comme un exercice.
List<int> ls;
int whatever = 123;
ls.Add(1);
ls.Add(235445);
ls.Add(whatever);
La mise en œuvre est similaire à n'importe quel Tableau de la Liste de classe là-bas. J'ai un T* vector
membre où je stocke les éléments, et lorsque ce stockage est sur le point d'être complètement remplis, je le redimensionner.
Veuillez noter que ce n'est pas pour être utilisé dans la production, ce n'est qu'un exercice. Je suis bien conscient de vector<T>
et amis.
Maintenant, je veux faire une boucle par les éléments de ma liste. Je n'aime pas utiliser for(int i=0;i<n; i==)
. J'ai tapé for
dans visual studio, attendu pour Intellisense, et il m'a proposé ceci:
for each (object var in collection_to_loop)
{
}
De toute évidence, cela ne fonctionne pas avec ma Liste de mise en œuvre. J'ai pensé que je pouvais faire quelques macro de la magie, mais cela se sent comme un énorme hack. En fait, ce qui me dérange le plus, c'est en passant le type comme ça:
#define foreach(type, var, list)\
int _i_ = 0;\
##type var;\
for (_i_ = 0, var=list[_i_]; _i_<list.Length();_i_++,var=list[_i_])
foreach(int,i,ls){
doWork(i);
}
Ma question est: est-il possible de faire cette Liste personnalisée de travail en classe avec un foreach-like
boucle?
- vous pouvez écrire un
begin()
et unend()
fonctions de membre et un itérateur de type pour votre classe pour la rendre foreach compatible.
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, la syntaxe d'un
for-each
boucle dansC++
est différente deC#
(c'est aussi appeléerange based for loop
. Il est de la forme:Ainsi, par exemple, avec un
std::vector<int> vec
, il serait quelque chose comme:Sous les couvertures, elle utilise le
begin()
etend()
membre des fonctions qui retournent des itérateurs. Par conséquent, pour permettre à votre classe personnalisée d'utiliser unfor-each
boucle, vous devez fournir unbegin()
et unend()
fonction. Ceux-ci sont généralement surchargés, en retour, soit uniterator
ou unconst_iterator
. La mise en œuvre des itérateurs peut être difficile, mais avec un vecteur comme la classe, il n'est pas trop dur.Avec ces mises en œuvre, vous pouvez avoir recours à une gamme de boucles comme ci-dessus.
Laisser
iterable
être de typeIterable
.Puis, afin de faire
compiler, il doit être appelé
Type
etIType
et il doit y avoir des fonctionsIType
doit fournir les fonctionsL'ensemble de la construction est vraiment sophistiqué sucre syntaxique pour quelque chose comme
où, au lieu de
Type
, tout type compatibles (tels queconst Type
ouType&
) peut être utilisé, ce qui aura des incidences prévisibles (constness de référence au lieu de copier etc.).Depuis l'ensemble de l'expansion qui se passe du point de vue syntaxique, vous pouvez également modifier la déclaration des opérateurs de bits, par exemple *il renvoyer une référence ou d'avoir != prendre un
const IType& rhs
en tant que de besoin.Notez que vous ne pouvez pas utiliser le
for (Type& x : iterable)
forme si*it
ne pas renvoyer une référence (mais si elle renvoie une référence, vous pouvez également utiliser la version de la copie).Note également que
operator++()
définit la préfixe version de la++
opérateur -- toutefois, il sera également utilisé comme la postfix exploitant, à moins que vous définissez explicitement un postfix++
. La distance-pour ne compilera pas si vous ne fournir qu'un postfix++
, qui btw.peut être déclarée commeoperator++(int)
(dummy argument int).Minimale de travail exemple:
sortie
Vous pouvez le faux variait pour chaque (par exemple, pour les anciens compilateurs C++) avec la macro suivante:
(utiliser declspec ou passer IType si votre compilateur ne dispose même pas d'auto).
De sortie:
Comme vous pouvez le voir,
continue
etbreak
sera de travailler avec cette grâce à sa construction compliquée.Voir http://www.chiark.greenend.org.uk/~sgtatham/mp/ pour plus de C-préprocesseur de piratage pour créer des structures de contrôle.
Que la syntaxe Intellisense suggéré est pas du C++, ou c'est quelque MSVC extension.
C++11 a gamme pour les boucles pour itérer sur les éléments d'un conteneur. Vous avez besoin de mettre en œuvre
begin()
etend()
fonctions de membre pour votre classe sur le retour des itérateurs pour le premier élément, et un seul après le dernier élément, respectivement. Qui, bien sûr, signifie que vous avez besoin pour mettre en œuvre adapté les itérateurs pour votre classe ainsi. Si vous voulez vraiment aller dans cette voie, vous pouvez regarder la Coup de pouce.IteratorFacade; il réduit beaucoup de la douleur de la mise en œuvre des itérateurs vous-même.Après cela, vous serez en mesure d'écrire ceci:
Aussi, puisque vous êtes novice en C++, je tiens à vous assurer que vous savez de la bibliothèque standard a plusieurs conteneur classes.
C++ n'a pas le
for_each
fonction de boucle dans sa syntaxe. Vous devez utiliser le c++11 ou utilisez la fonction de modèle std::for_each.Comme @yngum l'indique, vous pouvez obtenir le VC++
for each
extension pour travailler avec n'importe quel type de collection en définissantbegin()
etend()
méthodes de la collection retour personnalisé itérateur. Votre itérateur a tour de mettre en œuvre l'interface nécessaire (déréférencement de opérateur de, opérateur d'incrémentation, etc). J'ai fait cela pour envelopper toutes les classes de collection MFC pour le code de legs. C'est un peu de travail, mais peut être fait.