[C++]Quelques questions
Hello,
Je suis débutante et aurai quelques questions à vous posez
j'ai 3 class Animal, Tigre, Test
Tigre hérite de Animal
Comment s'écrit la méthode augmenter_taille
Est-ce que cette écriture est possible :
Si ce n'est pas le cas, comment faire pour ajouter des Tigres dans le tableau ?
Merci
Je suis débutante et aurai quelques questions à vous posez
j'ai 3 class Animal, Tigre, Test
Tigre hérite de Animal
class Test{ Animal [] tabAnimaux; //tableaux contenant les animaux int taille; //taille du tableaux int nbElements; //nombres de cases libres du tableaux void augmenter_taille(int nb){ //? }
Comment s'écrit la méthode augmenter_taille
int main(){ Animal [] animaux; for(int i=0; i<50; i++) animaux [i] = new Tigre(); } }
Est-ce que cette écriture est possible :
animaux [i] = new Tigre(...);
Si ce n'est pas le cas, comment faire pour ajouter des Tigres dans le tableau ?
Merci
7 réponses
Allocation et classe Test
Bon alors attention car new crée une instance et retourne l'adresse de l'instance. De plus qui dit new dit delete. Donc le plus simple c'est d'appeler directement le constructeur, ce qui évite les soucis d'allocation.
Attention aussi, car tu veux affecter animaux[i] alors que le tableau n'est pas alloué.
En gros ça donne :
Si tu ne connais pas la taille a priori de ton tableau, le plus simple c'est d'utiliser la classe std::vector :
L'avantage de la classe std::vector c'est qu'elle fait exactement ce que tu essayes de faire dans ta classe Test. Pour plus d'infos :
https://community.hpe.com/t5/custom/page/page-id/HPPSocialUserSignonPage?redirectreason=permissiondenied&referer=https%3A%2F%2Fcommunity.hpe.com%2Ft5%2FServers-Systems-The-Right%2FSGI-com-Tech-Archive-Resources-now-retired%2Fba-p%2F6992583
Les méthodes
Si tu as besoin de réimplémenter des méthodes dans la classe fille, utilise le mot clé virtual.
Bonne chance
Bon alors attention car new crée une instance et retourne l'adresse de l'instance. De plus qui dit new dit delete. Donc le plus simple c'est d'appeler directement le constructeur, ce qui évite les soucis d'allocation.
Attention aussi, car tu veux affecter animaux[i] alors que le tableau n'est pas alloué.
En gros ça donne :
Animal [50] animaux; for(int i=0; i<50; i++) animaux [i] = Tigre(); }
Si tu ne connais pas la taille a priori de ton tableau, le plus simple c'est d'utiliser la classe std::vector :
#include <vector> #include <iostream> int main(){ unsigned int n=28; std::vector<Animal> animaux; for(unsigned int i=0;i<n;++i) animaux.push_back(Tigre()); std::cout << "Il y a " << animaux.size() << " animaux" << std::endl; return 0; }
L'avantage de la classe std::vector c'est qu'elle fait exactement ce que tu essayes de faire dans ta classe Test. Pour plus d'infos :
https://community.hpe.com/t5/custom/page/page-id/HPPSocialUserSignonPage?redirectreason=permissiondenied&referer=https%3A%2F%2Fcommunity.hpe.com%2Ft5%2FServers-Systems-The-Right%2FSGI-com-Tech-Archive-Resources-now-retired%2Fba-p%2F6992583
Les méthodes
#include <iostream> class Plop{ protected: int x; public: Plop(int x0=0):x(x0){} void f(){ std::cout << x << std::endl; } }; // Attention à bien faire un héritage public !!! class Plop_fille : public Plop{ //... } int main(){ Plop p = Plop(4); p.f(); Plop_fille p = Plop_fille(4); p.f(); return 0; }
Si tu as besoin de réimplémenter des méthodes dans la classe fille, utilise le mot clé virtual.
Bonne chance
Merci de la réponse.
Dans le cas ou il y a héritage, par exemple une classe B hérite d'une classe A pour faire ceci :
Il faut donc obligatoirement crée un destructeur pour pouvoir utiliser new, c'est ça ?
autre question :
Comment fait-on pour détruire un tableau a 2 dimensions en C++.
Par exemple pour détruire le tableau [10][30]
et pour la destruction d'un int, double etc ...
int valeur;
Merci
Dans le cas ou il y a héritage, par exemple une classe B hérite d'une classe A pour faire ceci :
A a = new B();
Il faut donc obligatoirement crée un destructeur pour pouvoir utiliser new, c'est ça ?
autre question :
Comment fait-on pour détruire un tableau a 2 dimensions en C++.
Par exemple pour détruire le tableau [10][30]
et pour la destruction d'un int, double etc ...
int valeur;
Merci
Non en fait tu as toujours un destructeur par defaut. Si tu implémentes un destructeur, il tu "delete" tous les objets que tu as alloué avec un "new" dans le constructeur. Personnellement je n'utilise jamais de new, et donc jamais de delete.
Exemple
Attention à bien associer les news et les delete au même niveau car sinon c'est le meilleur moyen de faire des double free ou d'oublier de désallouer de la mémoire. En particulier si l'on considère cet exemple
l'objet pointé par adresse a été créé a l'extérieur de la classe mamie, et donc la classe mamie n'a pas à désallouer ce pointeur. Dans le cas de la classe tapir par contre, le constructeur a bien alloué le pointeur donc il est normal que le destructeur le libère. Mais comme je te l'ai dit tout à l'heure normalement tu peux presque tout le temps te passer des news.
Allocation statique et dynamique
Il faut bien voir qu'en C (ou C++) déclarer un int x[50], c'est comme si tu déclarais un int. Pas de malloc, pas de new, donc pas de free ou de delete, la variable est automatiquement détruite à la fin du "scope"
A chaque fois que tu atteins une fin de scope les variables locale crées dans ce scope sont désallouées (et éventuellement recrée si on est dans un boucle, comme par exemple pour z)
Bonne chance
Exemple
class tapir{ //... }; class plop{ protected: tapir *t; public: plop(unsigned int n=0){ t = new tapir(); } ~plop(){ delete t; } };
Attention à bien associer les news et les delete au même niveau car sinon c'est le meilleur moyen de faire des double free ou d'oublier de désallouer de la mémoire. En particulier si l'on considère cet exemple
class mamie{ protected: void *adresse; public: mamie(void *a):adresse(a){} };
l'objet pointé par adresse a été créé a l'extérieur de la classe mamie, et donc la classe mamie n'a pas à désallouer ce pointeur. Dans le cas de la classe tapir par contre, le constructeur a bien alloué le pointeur donc il est normal que le destructeur le libère. Mais comme je te l'ai dit tout à l'heure normalement tu peux presque tout le temps te passer des news.
Allocation statique et dynamique
Il faut bien voir qu'en C (ou C++) déclarer un int x[50], c'est comme si tu déclarais un int. Pas de malloc, pas de new, donc pas de free ou de delete, la variable est automatiquement détruite à la fin du "scope"
{// <--- début du scope de x int x[50]; if(...){// <--- début du scope de y char y; }// <--- fin du scope de y for(...){// <--- début du scope de z long p; }// <--- fin du scope de z } // <--- fin du scope de x
A chaque fois que tu atteins une fin de scope les variables locale crées dans ce scope sont désallouées (et éventuellement recrée si on est dans un boucle, comme par exemple pour z)
Bonne chance
Tu dis que tu n'utilises jamais de new mais comment est-ce que tu fais lorsqu'il y a de l'héritage ?
Par exemple, admettons qu'on ait une liste d'Animaux :
Et qu'Animal est la classe mère de Tigre et Serpent.
Pour ajouter des Tigre ou Serpent à cette liste, il faut faire :
pour ajouter un tigre ou
pour ajouter un Serpent.
Si tu n'utilises pas de new, comment est-ce que tu ferais pour pouvoir utiliser cette liste ?
Par exemple, admettons qu'on ait une liste d'Animaux :
vector<Animal*> listes;
Et qu'Animal est la classe mère de Tigre et Serpent.
Pour ajouter des Tigre ou Serpent à cette liste, il faut faire :
Animal* tigre = new Tigre(); listes.push_back(tigre);
pour ajouter un tigre ou
Animal* serpent = new Serpent(); listes.push_back(serpent);
pour ajouter un Serpent.
Si tu n'utilises pas de new, comment est-ce que tu ferais pour pouvoir utiliser cette liste ?
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Bon déjà un vecteur ce n'est pas une liste parce que c'est adjacent en mémoire, donc c'est plus proche du tableau que de la liste.
Ensuite je n'utilise des pointeurs que quand c'est nécessaire (ie si l'objet a déjà été créé en mémoire, et auquel cas je récupère son adresse avec l'opérateur &). Sinon je stocke directement l'objet.
Exemple
Ensuite je n'utilise des pointeurs que quand c'est nécessaire (ie si l'objet a déjà été créé en mémoire, et auquel cas je récupère son adresse avec l'opérateur &). Sinon je stocke directement l'objet.
Exemple
#include <vector> #include <iostream> struct plop{ double i[10000]; // un plop c'est gros :-) int x; plop(x0=0):x(x0){} }; int main(){ const unsigned int n = 69; // Je crée plein d'objets plop std::vector<plop> u(n); for(unsigned int i=0;i<n;++i) u[i] = plop(2*i + 3); // je stocke l'objet // Je veux réutiliser ces objets mais ils // sont déjà crées donc je vais chopper // leur adresse qui elle, est beaucoup // plus petite (la taille d'une adresse) std::vector<plop *> v(n); for(unsigned int i=0;i<n;++i) v[i] = &u[i]; // je stocke l'adresse // Afficher les (u[i]).x et les (v[i])->x for(unsigned int i=0;i<n;++i){ std::cout << i << '\t' << (u[i]).x << '\t' << (v[i])->x << std::endl; } return 0; }
Salut.
Pour reprendre ton exemple :
l'intéret c'est que serpent reste un Serpent au sein du tableau "listes"
C'est à dire que normalement (si Mamiemando pouvait confirmé :) il est possible que ça ne soit valable que pour les membres virtual) si serpent est le premier membre de listes, en fesant listes[0]-> tu peux accéder au données propres à Serpent.
Pour reprendre ton exemple :
Serpent serpent(); listes.push_back(&serpent);
l'intéret c'est que serpent reste un Serpent au sein du tableau "listes"
C'est à dire que normalement (si Mamiemando pouvait confirmé :) il est possible que ça ne soit valable que pour les membres virtual) si serpent est le premier membre de listes, en fesant listes[0]-> tu peux accéder au données propres à Serpent.
En fait c'est plutôt au niveau des dynamic_cast qu'il faut regarder, mais de manière générale, c'est mal de mélanger les torchons et les salades.
Moi je te conseille de mettre dans la mesure du possible dans un container uniquement des objets homogènes, ou de partir du principe que les objets stockés dans ce container sont du type passé en paramètre template du container.
Moi je te conseille de mettre dans la mesure du possible dans un container uniquement des objets homogènes, ou de partir du principe que les objets stockés dans ce container sont du type passé en paramètre template du container.