Question sur le Javaquarium en C++

Le problème exposé dans ce sujet a été résolu.

Bonjour à tous !
Je viens de finir le tutoriel sur la POO en C++ et je vous avoue que je trouve ce concept passionnant ! Je me suis donc lancé dans l'exercice du Javaquarium en C++. Je vous montre ce que j'ai fait pour le moment, les questions suivront. Voici mes codes (c'est vraiment le début !) :
Aquarium.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "Aquarium.h"

// Compteur :
unsigned int Aquarium::s_nbPoissons(0);
unsigned int Aquarium::s_nbAlgues(0);

// Classe Aquarium :
// Constructeur :
Aquarium::Aquarium()
{
}

// Destructeur :
Aquarium::~Aquarium()
{
}

// Accesseurs :
unsigned int Aquarium::getNbPoissons() const
{
    return nbPoissons;
}

unsigned int Aquarium::getNbAlgues() const
{
    return nbAlgues;
}

// Méthodes :
void Aquarium::ajouterPoisson(string nom, char sexe)
{
    ++s_nbPoissons;
}

void Aquarium::ajouterAlgue()
{
    ++s_nbAlgues;
}

Poisson.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <string>
#include "Poisson.h"

using namespace std;

// Constructeur :
Poisson::Poisson(string nom, char sexe) : m_nom(nom), m_sexe(sexe)
{
}

// Destructeur :
Poisson::~Poisson()
{
}

// Méthodes :
string getNom() const
{
    return m_nom;
}

char getSexe() const
{
    return m_sexe;
}

Voilà, ce n'est pas grand chose, je le sais (je ne vous montre pas les .h, Algue.cpp et main.cpp car ils ne sont pas utile ici je pense). Voici mes questions :
- Les compteurs doivent-ils faire parti de la classe Aquarium ou de leur classe respective ?
- Comment instancier un nouveau poisson avec la méthode Aquarium::ajouterPoisson ? J'imagine que je vais devoir passer par des pointeurs, mais je ne peux pas faire :

1
2
3
4
5
void Aquarium::ajouterPoisson(string nom, char sexe)
{
    poisson = new Poisson(nom, sexe);
    ++s_nbPoissons;
}

Car je n'utilise pas les pointeurs et que poisson n'existe pas… Et il en va de même pour la méthode Aquarium::ajouterAlgue.

Merci de votre aide et bonne journée.

+0 -0

Lu'!

Quand tu postes le code d'une classe, commence par montrer sa déclaration (ses *.h justement), une bonne part de sa bonne conception réside dans l'interface (les fonctions publiques) que tu lui auras attribué.

  • Les compteurs doivent-ils faire parti de la classe Aquarium ou de leur classe respective ?

Wizix

Aucun des deux. Et surtout pas le second ! Sinon, comment je ferai si par exemple je voulais deux aquarium ?

Tes poissons, tu les mets dans un conteneur (typiquement std::vector) qui fait partie des attributs de ta classe Aquarium. A partir de là, le nombre de poissons dans l'aquarium, c'est ton_vector.size().

  • Comment instancier un nouveau poisson avec la méthode Aquarium::ajouterPoisson ? J'imagine que je vais devoir passer par des pointeurs, mais je ne peux pas faire :
1
2
3
4
5
void Aquarium::ajouterPoisson(string nom, char sexe)
{
  poisson = new Poisson(nom, sexe);
  ++s_nbPoissons;
}

Car je n'utilise pas les pointeurs et que poisson n'existe pas… Et il en va de même pour la méthode Aquarium::ajouterAlgue.

Wizix

J'imagine que tu vas faire cette exercice par dérivation de la classe de base "Poisson" en différentes sous espèces (en tant qu'exercice pour pratique c'est bien, mais en vrai on ne veut pas faire comme ça - à noter que cette technique est plus complexe à mettre en place).

Dans une optique POO, les poissons ont une sémantique d'entité, en particulier parce qu'ils sont dérivables.

Comme ils ont une sémantique d'entité, ils ne sont ni copiable ni affectables (et tu dois interdire ces deux opérations). De plus, comme ils sont polymorphique, tu seras obligé de les manipuler par l'intermédiaire de pointeurs ou de référence. Et si tu veux les stocker dans un conteneur qui en sera responsable, tu devras le faire avec des pointeurs … intelligents (en C++, les pointeurs nus ne doivent pas être responsables des ressources).

Typiquement ici, le seul responsable des poissons, c'est l'aquarium, par extension, c'est le vector qui va contenir les poissons. Mais comme chaque élément de ce vector doit être un pointeur (polymorphisme oblige), il faudra faire en sorte que chacun de ses pointeurs soit l'unique possesseur du poisson qu'on lui donne. Cela tombe bien, c'est le boulot de std::unique_ptr.

1
std::vector<std::unique_ptr<Poisson>> mes_poissons;

Donc pour ajouter ton poisson au conteneur :

1
mes_poissons.push_back(std::make_unique<Poisson>(/*paramètres*/));

Enfin, tu voudras sans doute pouvoir ajouter des poissons de types différents. Auquel cas, tu pourras au choix :

  • rendre cette fonction générique sur le type de poisson à ajouter,
  • recevoir un pointeur unique sur un poisson en entrée de "ajouter" et déplacer ce pointeur dans le vector
  • passer par une factory renvoyant des poissons déjà protégés par leur unique_ptr.

Si tu as d'autres questions n'hésite pas.

Ciao.

Merci beaucoup pour cette réponse claire et vraiment complète!
Je vais essayer de traduire tout ça, je ré-éditerais ou posterais à la suite quand j'aurais bien compris ce que tu m'expliques!
Enfaite c'est surtout ce paragraphe qui me gêne :

J'imagine que tu vas faire cette exercice par dérivation de la classe de base "Poisson" en différentes sous espèces (en tant qu'exercice pour pratique c'est bien, mais en vrai on ne veut pas faire comme ça - à noter que cette technique est plus complexe à mettre en place).

Dans une optique POO, les poissons ont une sémantique d'entité, en particulier parce qu'ils sont dérivables.

Comme ils ont une sémantique d'entité, ils ne sont ni copiable ni affectables (et tu dois interdire ces deux opérations). De plus, comme ils sont polymorphique, tu seras obligé de les manipuler par l'intermédiaire de pointeurs ou de référence. Et si tu veux les stocker dans un conteneur qui en sera responsable, tu devras le faire avec des pointeurs … intelligents (en C++, les pointeurs nus ne doivent pas être responsables des ressources).

Comme ils ont une sémantique d'entité, ils ne sont ni copiable ni affectables (et tu dois interdire ces deux opérations). De plus, comme ils sont polymorphique, tu seras obligé de les manipuler par l'intermédiaire de pointeurs ou de référence. Et si tu veux les stocker dans un conteneur qui en sera responsable, tu devras le faire avec des pointeurs … intelligents (en C++, les pointeurs nus ne doivent pas être responsables des ressources).

Ksass`Peuk

Merci encore pour ta réponse!

+0 -0

Alors je me lance !

Comme ils ont une sémantique d'entité, ils ne sont ni copiable ni affectables

Mmmmm.. Pourquoi?!

De plus, comme ils sont polymorphique

Je ne comprend pas pourquoi ils doivent être polymorphique…
Et après c'est pire quand les pointeurs intelligent se ramènent ! :lol: Qu'est ce que ce unique_ptr ?!
Et si j'ai bien compris, tu fais un vecteur de pointeurs qui pointent vers une instance de la classe poisson ?

Comme ils ont une sémantique d'entité, ils ne sont ni copiable ni affectables

Mmmmm.. Pourquoi?!

Wizix

Voir le lien sur la sémantique d'entité. Chaque poisson est un individu unique.

De plus, comme ils sont polymorphique

Je ne comprend pas pourquoi ils doivent être polymorphique…

Wizix

Le but de cet exercice est de travailler avec des éléments qui peuvent faire diverses actions mais de manières différentes (et même potentiellement sur des objets différents). Tyiquement, par la suite, tu auras des poissons Carnivores, des Herbivores, des qui peuvent changer de sexe, etc … Tout ça va induire des comportements qui vont varier d'une bestiole à l'autre.

Il y a deux manières de résoudre l'exercice, soit une approche par composant (voir le lien que j'ai déjà mis) mais pour un débutant, elle n'est pas forcément facile à appréhender. Soit de manière purement en OO donc avec des interfaces définissant des comportements (attention à l'ISP et au DIP) et des variantes dans les implémentations de ces composants : du polymorphisme.

Et après c'est pire quand les pointeurs intelligent se ramènent ! :lol: Qu'est ce que ce unique_ptr ?!

Wizix

C'est un pointeur aussi bête que possible (c'est pour ça qu'il est intelligent), il reçoit une ressource et dès qu'il est détruit, il détruit la ressource. Il est non-copiable et non-affectable, donc il ne partage pas sa ressource.

Et si j'ai bien compris, tu fais un vecteur de pointeurs qui pointent vers une instance de la classe poisson ?

Wizix

Oui.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte