J'essaie de m'enseigner moi-même C ++ et l'une des exercices traditionnels «nouvelles langues» que j'ai toujours utilisées est de mettre en œuvre une structure de données, comme un arbre binaire ou une liste liée. En Java, cela a été relativement simple: je pourrais définir un noeud de classe qui a conservé une variable d'instance Je ne trouve pas de manière similaire, idiomatique C ++ de stocker "tout type d'objet". En C, j'utiliserais un indicateur Question de bonus: Si ce n'est pas le cas, et j'ai besoin de continuer à utiliser des pointeurs Void, quel est le moyen "droit" de stocker un Data d'objet code>, de sorte que quelqu'un puisse stocker n'importe quel type d'objet dans chaque nœud de la liste ou de l'arbre. (Plus tard, j'ai travaillé à la modification de cela en utilisant des génériques; ce n'est pas la question de cette question.) P>
annulation code>; La même chose fonctionne pour C ++, évidemment, mais je rencontre des problèmes lorsque je construis une instance de
std :: string code> et essayez de le stocker dans la liste / arborescence (quelque chose à propos d'un casting non valide de < Code> std :: string & code> to
vide * code>). Y a-t-il une telle manière? C ++ a-t-il équivalent à l'objet de Java (ou NSOBJECT DE CY-C)? P>
std :: string code> dans un
vide * code>? Je suis tombé sur
static_cast
6 Réponses :
C ++ n'a pas d'objet de base que tous les objets héritent de, contrairement à Java. L'approche habituelle de ce que vous voulez faire serait d'utiliser Modèles . Tous les conteneurs de la bibliothèque C ++ standard utilisent cette approche.
Contrairement à Java, C ++ ne s'appuie pas sur le polymorphisme / l'héritage pour mettre en œuvre des conteneurs génériques. En Java, tous les objets héritent de Vous pouvez alors créer un objet code>, et une classe peut donc être insérée dans un conteneur qui prend un objet
code>. Les modèles C ++ sont toutefois compilés des constructions de temps qui indiquent au compilateur de générer une classe différente pour chaque type que vous utilisez. Donc, par exemple, si vous avez: p>
myContainer code> qui prend
std :: string code> objets, et un autre myContainer qui prend
int code> s. p>
Est-il sûr pour moi d'analoguer mentalement des modèles de génériques Java?
Pas vraiment. Ils sont très différents, même si la syntaxe est superficiellement la même.
Pour élaborer, les génériques Java sont un mécanisme d'exécution qui repose sur l'héritage et le polymorphisme. Les modèles C ++ sont des constructions de compilation qui indiquent le compilateur à générer du code pour chaque type paramétré. Voir ma réponse modifiée pour plus d'informations.
En fait, croyez-le ou non, les modèles C ++ ont effectivement plus en commun avec C Macros que Java Generics. Bien sûr, ils sont beaucoup plus sûrs et plus puissants que les macros.
@CHARDLES: C'est comme dire que le Dr X est plus en commun avec le Dr Mangler que le Dr Y. La comparaison n'est pas utile et trompeuse en même temps.
@Martin, je peux voir votre point, mais les modèles sont si souvent comparés aux génériques Java (en raison d'une similitude de syntaxe, et superficiellement, une similitude en fonction), lorsqu'il est en réalité, ils sont drastiquement différents. (Génération de code temporel de compilation par rapport à un polymorphisme de temps d'exécution.) Je pensais que la comparaison avec C macros (qui sont également un mécanisme de génération de code de compilération de la compilation) a aidé à mettre en évidence cela. Mais vous avez raison, les modèles sont également très différents des macros, qui ne sont rien de plus qu'un mécanisme de prétraitement de recherche / remplacement.
@Chals: Ils sont en fait conceptuellement similaires aux macros LISP communes, mais cela ne va pas aider beaucoup de gens à saisir le concept.
Quand venant i> de Java Generics, je dirais que cela est en fait sûr de penser à des modèles C ++ en tant que génériques initialement, car la plupart des choses que vous attendez du travail de la même manière (à l'exception de les types). Bien sûr, les modèles sont beaucoup plus que cela, mais comme une première itération, cela devrait faire. Un problème plus important s'approche des génériques Java comme si elles sont des modèles C ++ (c'est-à-dire l'autre direction à l'auteur de la question).
Alors, que si je voulais ajouter une chaîne et quelque chose d'autre comme un vecteur à un vecteur. Comme dans je veux avoir une collection d'objets différents. En Java, vous venez de faire une arrayliste
Qu'est-ce que vous recherchez sont des modèles. Ils vous permettent de créer des cours et des fonctions qui vous permettent de prendre n'importe quel type de données. P>
Vous devriez être capable de lancer un Cependant, comme d'autres l'ont dit, une meilleure façon de le faire est avec des modèles p> Void * code> dans une chaîne
code> à l'aide de moulages de style C standard. N'oubliez pas qu'une référence n'est pas traitée comme un pointeur lorsqu'il est utilisé, il est traité comme un objet normal. Donc, si vous passez une valeur par référence à une fonction, vous devez toujours la réfriger pour obtenir son adresse. p>
Les couts de style C doivent être découragés en C ++.
Toutefois, si vous devez stocker différents types d'objets dans le même conteneur, vous pouvez faire C'est la manière dynamique, en stockant Un pointeur intelligent est plus facile à utiliser. Exemple avec boost :: smart_ptr code>: p>
Vous pouvez regarder Boost :: Toute classe. Il est de type sécurisé, vous pouvez le mettre en collections standard et vous n'avez pas besoin de créer un lien avec une bibliothèque, la classe est implémentée dans le fichier d'en-tête.
Il vous permet d'écrire du code comme celui-ci: P>
#include <list> #include <boost/any.hpp> typedef std::list<boost::any> collection_type; void foo() { collection_type coll; coll.push_back(boost::any(10)); coll.push_back(boost::any("test")); coll.push_back(boost::any(1.1)); }
static_cast<char*>(str.c_str()) looks odd to me. str.c_str() retrieves the C-like string, but with type const char *, and to convert to char * you'd normally use const_cast<char *>(str.c_str()). Except that that's not good to do, since you'd be meddling with the internals of a string. Are you sure you didn't get a warning on that?You should be able to use static_cast<void *>(&str). The error message you got suggests to me that you got something else wrong, so if you could post the code we could look at it. (The data type std::string& is a reference to a string, not a pointer to one, so the error message is correct. What I don't know is how you got a reference instead of a pointer.)And, yes, this is verbose. It's intended to be. Casting is usually considered a bad smell in a C++ program, and Stroustrup wanted casts to be easy to find. As has been discussed in other answers, the right way to build a data structure of arbitrary base type is by using templates, not casts and pointers.
Pourquoi cette question a-t-elle été descendue?
Je suis intéressé à savoir aussi - je n'ai pas pu trouver de dupe ou de rien ...
C'est comme la vieille blague. Patient: Ça fait mal quand je fais ça. Docteur: Ne fais pas ça. En C ++, ne faites pas une collection de "quoi que ce soit".
@ Jerry Coffin- +1, avec la mise en garde qui pour apprendre, alors tout se passe. Il n'y a rien de mal à mettre en œuvre une collection en C ++ pour apprendre les constructions de langue, mais lorsque vous avez terminé l'apprentissage, jetez-la.