Objets, Classes, Fonctions avec objets en paramétres, *, & :Prob.

Objets, Classes, Fonctions avec objets en paramétres, *, & :Prob. - C++ - Programmation

Marsh Posté le 18-10-2002 à 16:13:57    

Alors, je vous explique.  
(Environnement : g++ 2.96, linux)
Je suis en train de faire un programme en C++, avec des classes etc.
 
Il se trouve que une des classes est composée d'un objet, ou de plusieurs
objets d'une des autres classes. J'avais par exemple cité l'exemple  
d'un CMeuble composé de CTiroirs.
 
Prenons le cas ou ma classe n'a besoin que d'un seul objet en paramétre:
Exemple, une CBouteille, lors de sa construction nécessite un CContenu.
Alors la les ennuis arrivent.
Je voudrais que tout cela soit dynamique : exemple.
 
Je Crée une CBouteille, avec dans le constructeur en paramétre un (1 seul) CContenu.
Avec l'objet CBouteille, je peux faire une fonction pour savoir le volume contenu dans la bouteille.
 
blabla.get_volume() par exemple.
Je voudrais donc que si APRES la déclaration de ma bouteille, je modifie mon objet CContenu(utilisé lors
de la construction de la bouteille), si je fais un get_volume() sur ma bouteille
je dois pouvoir avoir le nouveau volume inséré...
Et la, je bloque, avec les pointeurs, les références, etc...
 
Faut il que dans le constructeur, je mette en paramétre un CContenu* ou un
simple CContenu ?
 
Autre sujet (étroitement relaté tout de meme), si dans mon cas CMeuble CTiroir je veux faire un Meuble composé de 3 tiroirs,
il convient, dans le constructeur, de l'appeller avec un tableau de pointeurs, pour que la aussi
ce soit dynamique ?
 
Si vous trouvez qqchose de flou n'hésitez pas a me le dire :)
Merci bcp !
 
 


---------------
Code Ami 3DS : 4725-8298-9418
Reply

Marsh Posté le 18-10-2002 à 16:13:57   

Reply

Marsh Posté le 18-10-2002 à 16:39:12    

CContenu*
 
utilise STL avec les std::vector et std::list


---------------
du bon usage de rand [C] / [C++]
Reply

Marsh Posté le 19-10-2002 à 03:12:54    

EUh, j'ai oublié de préciser, oublie les Vector/List et tout, je dois pas les utiliser :)


---------------
Code Ami 3DS : 4725-8298-9418
Reply

Marsh Posté le 19-10-2002 à 05:00:17    

Comme ça ?

Code :
  1. class CContenu{
  2. public:
  3. int quantite;
  4. CContenu(int q):quantite(q){}
  5. };
  6. class CLiquide:public CContenu{
  7. public:
  8.  CLiquide(int v):CContenu(v){}
  9. };
  10. class CVin:public CLiquide{
  11. public:
  12. CVin(int v):CLiquide(v){}
  13. void PrendreLaPartDesAnges(){ quantite--; }
  14. };
  15. class CContenant{
  16. public:
  17. CContenu* contenu;
  18. CContenant(CContenu* c):contenu(c){}
  19. };
  20. class CBouteille:public CContenant{
  21. public:
  22. CBouteille(CLiquide* l):CContenant(l){}
  23. int getVolume(){ return contenu->quantite; }
  24. };
  25. int main(){
  26. CVin vin(75);
  27. CBouteille bouteille(&vin);
  28. bouteille.getVolume(); //75
  29. vin.PrendreLaPartDesAnges();
  30. bouteille.getVolume(); //74
  31. return 0;
  32. }


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 20-10-2002 à 16:46:19    

Musaran, d'abord un grand merci.
Ensuite, je voudrais, si tu le veux bien, être éclairé sur 2-3 trucs...
 
Tout d'abord, tu as utilisé l'héritage pour :
CContenu->CLiquide->CVin
et CContenant->CBouteille
Pour CLiquide->CVin, je suis amplement d'accord, mais est-ce vraiment nécessaire, au sens modélisation, de hériter Liquide de Contenu ?
Enfin, en plus clair, faudrait-il changer des trucs (a part l'héritage des fonctions comme quantité() ) ?
Enfin, ca c plus du détail de conception
 
Par contre, je vois que tu met un CContenu* pour représenter les divers contenus d'un contenant.
Mais comment organiser précisément le constructeur avec tous les paramétres, et tout ? J'ai peur qu'il y ait plein de problemes avec les *,** etc..
 
Sinon, le principe de foncitonnement de ton main est exactement celui qui me pose problème.
 
En tout cas, merci bcp :)
a+ :hello:
 
 


---------------
Code Ami 3DS : 4725-8298-9418
Reply

Marsh Posté le 21-10-2002 à 05:01:21    

Modano a écrit a écrit :

est-ce vraiment nécessaire, au sens modélisation, de hériter Liquide de Contenu ?



Le liquide est un contenu... ça a donc un sens, au moins dans ton cas. Sinon, ton contenu a un liquide, ce qui est zarb.
Est-ce nécessaire ? Ça dépends de ce que tu veux faire.
 
Le problème, c'est que...

Code :
  1. CBouteille bouteille(&vin); //...bien qu'on remplisse la bouteille avec du vin...
  2. bouteille.contenu->PrendreLaPartDesAnges();//...le contenu n'est pas du vin, mais juste un contenu.


PrendreLaPartDesAnges() devrait être plutôt une méthode de la bouteille (c'est son bouchon qui évapores).
 
Si CContenu avait une fonction virtuelle, on pourrait voir qu'on a vraiment affaire à du vin.
 
Si les pointeurs te font peur, il y a les références, mais on vois moins la différence avec un objet copié.
Et surtout, on ne peut plus les changer après la construction !
 
Il faut un certain temps (et pas mal d'expérimentation) pour se faire au fonctionnement des objets et des hiérarchies.
Je n'ai pas de cours en tête, mais je sais qu'il y en a sur www.developpez.com (qualité variable).


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 21-10-2002 à 11:37:59    

Oui en fait tu as raison vu de ce point de vue, c moi qui me suis mal  
expliqué.
En fait, mon contenu a moi a dans ses membres un CLiquide* puisqu'en fait
il est composé de plusieurs liquides.
(d'ou mon non-héritage)
 
Et dans ce cas, lors de l'initialisation de ce CLiquide*, il faut faire
un tableau de pointeurs (CLiquide* liquides[nb]) ou un pointeur sur un
tableau (CLiquide* liquides=new CLiquide[nb]). Je pense qu'il faille
mieux utilser la premiere solution, pour que l'on puisse accéder directement
aux modifs faites sur les objets non ?
 
Mais autre question, comment on le déclare dans le constructeur ce tableau
de pointeurs ?
 
merci encore !


---------------
Code Ami 3DS : 4725-8298-9418
Reply

Marsh Posté le 23-10-2002 à 04:24:05    

Il y deux raisons d'utiliser l'allocation dynamique avec new:
1) Maîtriser la durée de vie de l'objet.
2) Le nombre d'éléments n'est connu qu'à l'exécution.
 
Un tableau si tu veux approprier et incorporer la liste de liquides.
Un pointeur si tu veux la partager, ou si le nombre n'est pas connu d'avance.
 
En brut:

Code :
  1. class CContenu{
  2. public:
  3. CLiquide* liquides[nb];
  4. CContenu(CLiquide l[]){ //synonyme de (CLiquide* l)
  5.  for(int i= 0 ; i<nb ; ++i)
  6.   liquides[nb]= l[nb];
  7. }
  8. };

C++ est gênant car il ne gère pas les tableaux correctement. Aucune protection contre les dépassements.
 
Mais puisqu'on est en C++, et que tu veux du dynamisme:

Code :
  1. #include <vector>
  2. using std::vector;
  3. class CLiquide{
  4. public:
  5. int volume;
  6. CLiquide(int v):volume(v){}
  7. };
  8. class CContenu{
  9. public:
  10. vector<CLiquide*>* liquides;
  11. CContenu(vector<CLiquide*>* l):liquides(l){}
  12. };
  13. int main(){
  14. CLiquide pastis(5);
  15. CLiquide eau(1);
  16. vector<CLiquide*> vl; //tableau dynamique vide
  17. vl.push_back(&pastis); //ajouter par adresse au vecteur
  18. CContenu ct(&vl); //lier au vecteur
  19. ct.liquides->push_back(eau); //ajouter
  20. vl[1]->volume= 2; //changer la dose d'eau
  21. return 0;
  22. }

Avec ça, tu peux partager la même dose dans plusieurs mélanges et dans plusieurs bouteilles si tu veux.
 
Maintenant, c'est toi qui connaît le problème, donc c'est à toi de structurer.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 23-10-2002 à 10:50:27    

Et bien grace a tes conseils avisés, en C++ j'ai réussi à créer mes multiples
structures et tout marche, a un détail prés. Si j'arrive à corriger
ce détail, ça sera parfait.
 
En gros, j'utilise des pointeurs sur des tableaux de pointeurs :
(genre CLiquide* liquides_contenus[]), et donc dans les classes
je trouve des membres de la forme citée.
 
Le problème, c'est que j'arrive à ce que ca marche bien que dans le cas
(trés génant j'avoue :) ) ou je fixe la taille du tableau de pointeur.
CLiquide* liquides_contenus[10] par ex. La, c'est facile a gérer
dans les constructeurs, dans les procédures d'ajout/suppression.
Maintenant, l'idéal serait de ne pas fixer cette taille et d'ajouter
dynamiquement.  
Je pensais que ct avec des new(), mais je rencontre alors beaucoup d'erreurs
de segmentation etc, alors en attendant j'ai laissé commme ca..  
Donc le probleme est dans la procédure d'ajout notamment, comment je fais ?
j'efface le tableau et je le recrée ? (Tout en sachant que je ne
veux pas perdre mes pointeurs qui en ce moment pointent bien :D )
 
 
Si toi ou qqn a une idée :) En tout cas, merci deja de tes lanternes !


---------------
Code Ami 3DS : 4725-8298-9418
Reply

Marsh Posté le 24-10-2002 à 03:33:21    

new/delete n'ont pas d'équivalent à réalloc, c'est comme ça. On peut faire:

Code :
  1. #include <algorithm>
  2. using std::copy;
  3. //fonction ici
  4. int** tab= ...; //size déjà alloué
  5. int** temp= new int*[newsize];
  6. copy(tab,tab+size,temp); //remplace une boucle for
  7. delete[] tab;
  8. tab= temp;


Si c'est pour que ça marche, utilises le "vector", il est fait exactement pour ça. vector::resize() pour redimensionner.
Si c'est pour apprendre les pointeurs de pointeurs... le contexte est favorable aux erreurs.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed