snoozriton
Messages postés12Date d'inscriptionjeudi 22 décembre 2011StatutMembreDernière intervention12 novembre 2010
-
5 janv. 2010 à 20:56
snoozriton
Messages postés12Date d'inscriptionjeudi 22 décembre 2011StatutMembreDernière intervention12 novembre 2010
-
6 janv. 2010 à 13:19
Bonjour à tous,
étant en train d'étudier le C++, j'ai quelques soucis avec un exercice.
C'est un classique dont je vous donne l'énoncé :
[b]1. Définissez la classe Animal qui sera muni des champs age, sexe et nom.
2. Définissez les classe Chien, Chat et Lapin qui héritent de Animal ainsi
que des constructeurs pour chacune de ces classes.
3. On consid`ere un tableaux de cinq pointeurs sur la classe Animal. Faites les modifications n ́ecessaires pour proposer une fonction remplissant ce tableau `a l’aide d’informations entrées au clavier, sachant que l’utilisateur précisera si l’animal considéré est un chien, un chat ou un lapin.
4. Faites les modifications nécessaires pour proposer une fonction qui retourne l’age moyen des animaux du tableau.
5. Faites les modifications nécessaires pour proposer une fonction qui indique le nombre de chiens, de chats et de lapins présents dans le tableau.
6. Faites les modifications n ́ecessaires pour proposer une fonction qui affiche à l'écran toutes les caractéristiques des animaux contenus dans le tableau.
7. Faites les modifications nécessaires pour proposer une fonction qui supprime du tableau tous les chats et chiens mâles.
Lorsque l’utilisateur lance le programme, il doit se trouver face au menu suivant :
• pour remplir le tableau d’animaux, tapez 1.
• pour afficher à l'écran toutes les caract ́eristiques des animaux contenus
dans le tableau, tapez 2.
• pour connaitre l’age moyen des animaux du tableau, tapez 3.
• pour connaitre le nombre de chiens, de chats et de lapins pr ́esents dans le
tableau, tapez 4.
• Pour supprimer du tableau tous les chats et chiens mâles, tapez 5.
Si l’utilisateur tape 0, il sort du programme, sinon l’utilisateur teste la fonction de la question correspondant au numéro inscrit après tapez et on retourne au menu principal./b
Jusqu'ici, je n'ai jamais eu de problème avec les exercices simples sur les pointeurs ou les classes. Mais là, tout se mélange et je m'y perds quelque peu...
Je vous mets le début de code que j'ai fait. Ca compile mais ça plante lamentablement lorsque après la saisie d'un 2eme animal.
snoozriton
Messages postés12Date d'inscriptionjeudi 22 décembre 2011StatutMembreDernière intervention12 novembre 20101 6 janv. 2010 à 11:38
Encore moi ! Voilà donc ce que donne mon code pour le moment.
#include
#define SIZE 2
using namespace std;
class Animal{
protected:
int age;
char sexe;
string nom;
public:
Animal(int a=0, char s='F', string n=""){
age=a;
sexe=s;
nom=n;
}
void affiche(){
cout << age << " " << sexe << " " << nom;
}
virtual string type(){
return "Animal";
}
~Animal(){}
};
class Chien : public Animal {
private:
string race;
public:
Chien(int a=0, char s='F', string n="", string r="Chien"){
age=a;
sexe=s;
nom=n;
race=r;
}
void affiche(){
affiche();
cout << race << endl;
}
virtual string type(){
return race;
}
~Chien(){}
};
class Lapin : public Animal {
private:
string race;
public:
Lapin(int a=0, char s='F', string n="", string r="Lapin"){
age=a;
sexe=s;
nom=n;
race=r;
}
void affiche(){
affiche();
cout << race << endl;
}
virtual string type(){
return race;
}
};
class Chat: public Animal {
private:
string race;
public:
Chat(int a=0, char s='F', string n="", string r="Chat"){
age=a;
sexe=s;
nom=n;
race=r;
}
void affiche(){
affiche();
cout << race << endl;
}
virtual string type(){
return race;
}
};
int menu_animal () {
int choix;
cout << " 1 - Pour saisir un chat" <<endl;
cout << " 2 - Pour saisir un chien" <<endl;
cout << " 3 - Pour saisir un lapin" <<endl;
cout << endl << "Choix : ";
cin >> choix;
return choix;
}
void remplissage_tab(Animal **tab){
int i,a,choix;
string n;
char s;
for (i=0; i<SIZE; i++) {
cout << "Saisie de l'animal num " << i+1 << endl;
choix=menu_animal();
cout << "Saisissez son nom : ";
cin >> n;
cout << "Saisissez son age : ";
cin >> a;
cout << "Saisissez son sexe M ou F : ";
cin >> s;
switch(choix){
case 1 : tab[i] = new Chat(a,s,n);
break;
case 2 : tab[i] = new Chien(a,s,n);
break;
case 3 : tab[i] = new Lapin(a,s,n);
break;
}
}
}
void affichage_tab(Animal **tab){
int i;
cout << "Age " << "Sexe " << "Nom" << " Type" << endl;
for (i=0; i<SIZE; i++) {
tab[i]->affiche();
cout << " " <<tab[i]->type() << endl;
}
}
float age_moy(Animal **tab){
int i;
float som;
som=0;
for (i=0; i<SIZE; i++) {
som=som + tab[i]->age;
}
return som;
}
main(){
Animal * tab[SIZE];
remplissage_tab(tab);
affichage_tab(tab);
system("pause");
}
Mon souci est dans la fonction age_moy
j'ai besoin d'accéder à l'attribut age qui est, à l'heure actuelle, en protected.
Quel est le meilleur moyen pour pouvoir y accéder ?
Je ne dois pas pouvoir tout passer en public j'imagine.
Créer une méthode virtuelle qui me retourne l'age de l'animal ?
cptpingu
Messages postés3837Date d'inscriptiondimanche 12 décembre 2004StatutModérateurDernière intervention28 mars 2023123 5 janv. 2010 à 21:44
Plusieurs erreurs:
- Remplissage_tab(&tab[i],i); Non. remplissage_tab(tab, i); Pas besoin de re-re-décaler l'indice. i s'en charge déjà.
- char s=NULL, bizarre char n'est pas un pointeur. Devrait être initialisé à 'f' ou 'h'. En soit ce n'est pas faux, ça équivaut à s = 0 ou s = '\0'.
- Vire #include <stdlib.h> c'est du C, pas du C++. En C++ on utilise 0 plutôt que NULL (NULL vaut toujours 0). Si tu as besoin de stdlib, alors écrit #include <cstdlib>
- Jamais de using namespace std; voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
snoozriton
Messages postés12Date d'inscriptionjeudi 22 décembre 2011StatutMembreDernière intervention12 novembre 20101 5 janv. 2010 à 22:28
Dans l'exercice il est demandé de ne munir la Animal que des champs âge, sexe et nom.
J'ai un tableau de pointeurs sur la classe Animal (comme demandé).
J'instancie les éléments du tableau à l'aide des classes filles Chien, Chat et Lapin en fonction de ce que l'utilisateur souhaite saisir comme animal.
Comment puis-je retrouver à quel type d'animal correspond un élément du tableau sachant qu'il n'y a que âge, sexe et nom qui apparaissent.
Y a-t-il un moyen de retrouver à partir de quelle classe un élément a été instancié ?
J'espère être clair dans ma demande.
Et si quelqu'un peut jeter un oeil à mes constructeurs et destructeurs car c'est encore assez flou pour moi...
cptpingu
Messages postés3837Date d'inscriptiondimanche 12 décembre 2004StatutModérateurDernière intervention28 mars 2023123 5 janv. 2010 à 22:34
Il y a plusieurs solutions. Celle-ci n'est pas la meilleur, mais est simple à comprendre pour ton niveau actuel (pas de nouvelles notions nécessaires).
Met une méthode std::string type() dans chacune des classes, qui renvoit le vrai type de la classe.
Ex:
class A
{
public:
virtual std::string type()
{
return "Je suis A";
}
};
class B : public A
{
public:
virtual std::string type()
{
return "Je suis B";
}
};
A* a = new B;
a->type(); // Renverra Je suis B.
Virtual veut dire: La méthode a le droit d'être redéfinit dans la classe fille.
snoozriton
Messages postés12Date d'inscriptionjeudi 22 décembre 2011StatutMembreDernière intervention12 novembre 20101 5 janv. 2010 à 22:50
Merci CptPingu, cela me sera sans doute utile mais dans cet exercice, je ne vois pas comment je pourrai interpréter le résultat. Par exemple pour compter le nombre de chats, de chiens... ou Supprimer les chats et les chiens mâles.
Dans mon code, j'ai commencé à mettre une donnée membre race (que je devrais renommer en type plutôt) dans chaque classe fille.
C'est sans doute comme ça que je pourrai plus facilement m'en sortir.
Mais il me vient alors un autre problème. Sachant que cette donnée n'apparaitra pas dans le tableau constitué d'éléments, y a-t-il un moyen de retrouver cette donnée membre ?
cptpingu
Messages postés3837Date d'inscriptiondimanche 12 décembre 2004StatutModérateurDernière intervention28 mars 2023123 5 janv. 2010 à 23:11
Oui, si des méthodes publiques utilisent la race en interne, ce n'est pas gênant.
Ex:
class A
{
public:
virtual std::string type()
{
return "Je suis A";
}
};
class B : public A
{
public:
virtual std::string type()
{
// On considère que _race = "pouet";
return "Je suis B et la race est : " + _race;
}
private:
std::string _race;
};
A* a = new A;
A* b = new B;
a->type(); // Affichera "Je suis A"
b->type(); // Affichera "Je suis B et la race est : pouet"
snoozriton
Messages postés12Date d'inscriptionjeudi 22 décembre 2011StatutMembreDernière intervention12 novembre 20101 6 janv. 2010 à 08:07
Bonjour,
peux-tu m'expliquer pourquoi tu créés une nouvelle classe AnimalDeRace ?
Comment tu fais pour intégrer ton code de cette façon avec l'indentation ? Quand je fais un copier/coller, j'ai tout aligné à gauche comme tu as pu le voir dans le premier post...
cptpingu
Messages postés3837Date d'inscriptiondimanche 12 décembre 2004StatutModérateurDernière intervention28 mars 2023123 6 janv. 2010 à 10:12
peux-tu m'expliquer pourquoi tu créés une nouvelle classe AnimalDeRace ?
Parce que Chat, Chien et Lapin ont les mêmes propriétés. Donc je les factorise dans une classe au dessus, afin de ne pas répéter les mêmes choses. Je met "_race" et "affiche" dans AnimalDeRace, et je dis juste à Lapin, Chat et Chien d'en hériter. Pas besoin de réécrire trois fois la méthode affiche, ni d'avoir à réécrire 3 fois l'attribut _race.
Comment tu fais pour intégrer ton code de cette façon avec l'indentation ? Quand je fais un copier/coller, j'ai tout aligné à gauche comme tu as pu le voir dans le premier post...
Tu as des boutons de présentations dans la boîte de dialogue. Sinon tu ajoute un [ code=cpp] // Ton code /code (sans l'espace avant code).
cptpingu
Messages postés3837Date d'inscriptiondimanche 12 décembre 2004StatutModérateurDernière intervention28 mars 2023123 6 janv. 2010 à 12:05
(int a=0, char s='F', string n="")
On évite les champs par défaut. Le constructeur est là pour forcer l'initialisation de certains attributs. Tu annules une partie de son utilité en faisant cela.
using namespace std;
Encore une fois, jamais jamais de using namespace std; !
Lis ceci: Du bon usage du using namespace std
Les constructeurs doivent être virtuels.
Re-Regarde attentivement la version propre que je t'ai envoyé. Tu fais beaucoup d'erreur que je t'avais déjà corrigé.
j'ai besoin d'accéder à l'attribut age qui est, à l'heure actuelle, en protected.
Quel est le meilleur moyen pour pouvoir y accéder ?
snoozriton
Messages postés12Date d'inscriptionjeudi 22 décembre 2011StatutMembreDernière intervention12 novembre 20101 6 janv. 2010 à 13:19
Encore une fois, jamais jamais de using namespace std; !
Lis ceci: Du bon usage du using namespace std
J'ai bien vu ta remarque concernant le namespace std
Ce que je voulais te préciser c'est que mon prof l'utilise. Pas bien oui. J'ai donc laissé et adapté avec ce que tu m'avais donné.
Je vais aussi virer les valeurs par défaut des constructeurs.
Ok pour l'histoire de l'attribut. J'ai pigé le truc.