Classes, héritage et polymorphisme

Fermé
Neverbackdown Messages postés 1 Date d'inscription lundi 7 janvier 2013 Statut Membre Dernière intervention 7 janvier 2013 - 7 janv. 2013 à 19:22
mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 - 8 janv. 2013 à 01:17
Bonjour,


Je débute en C++ à la fac, j'en ai fais 3 mois à tout casser, on a fait le tour de pas mal de choses pour ne pas dire tout, m'en voilà rendu aux classes, polymorphisme etc

Mon partiel final étant prévu pour dans une dizaine de jours j'ai un sujet de l'année dernière que j'aimerai bien faire. J'ai commencé, essayé pas mal de choses, mes connaissances dans ce domaine étant un peu limitées j'aurai voulu avoir un peu de votre aide, si quelqu'un à suffisamment de patience à m'accorder. ( Nous codons sous le logiciel CodeBlocks )

Voilà le sujet :
https://imagesia.com/img196_4oj7
https://imagesia.com/img197_4oj8
https://imagesia.com/img198_4oj9

Voici mon code:

Fichier election.h
#ifndef ELECTION_H_INCLUDED
#define ELECTION_H_INCLUDED

class election 
{
protected:

int nbelecteurs;
int nbvotants;
int nbcandidats;
string* nomDesCandidats;
int* nbVoixDesCandidats;

public:

election(int nCand, string* noms);
virtual~election();
void saisieResultat();
void triResultat();
double tauxDeParticipation();
int suffragesExprimes();
double tauxDeBlancs();
void afficheResultatExprimes();
void afficheResultatElecteurs();
virtual void afficheSelectionnes()=0;
};



#endif // ELECTION_H_INCLUDED



Fichier legislative.h

#ifndef LEGISLATIVE_H_INCLUDED
#define LEGISLATIVE_H_INCLUDED

class legislative : public election
{
legislative (int nCand, string*noms)
};

#endif // LEGISLATIVE_H_INCLUDED


J'espère que jusqu'ici c'est bon normalement, maintenant c'est l'élaboration des fonctions dans les fichiers.cpp qui me posent pas mal de problèmes.

Fichier election.cpp

#include <iostream>
#include <string>
#include "election.h"

using namespace std;

election :: election (int nCand, string*noms)
{
nbelecteurs=0;
nbvotants=0;
nbcandidats=nCand;
noms[nbCandidats]= /* ???? recopier un tableau dans un autre 
                      tableau dynamique pointant vers je sais 
                       pas quoi ça me dépasse...*/
}


( Ne pouvons nous pas mettre de la couleur un peu ?)

1 réponse

mamiemando Messages postés 33076 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 avril 2024 7 748
Modifié par mamiemando le 8/01/2013 à 01:18
Non il n'y a pas de couleur sur le forum, malheureusement.

Quelques petites remarques. Pour pouvoir parler du type std::string, il faut au préalable dans election.h inclure le header correspondant <string> (sans .h car c'est le header C++ de la STL qu'on inclue ; si on veut inclure le header <string.h> du langage C, on incluera <cstring>). De plus il me paraît plus propre de nommer tes headers ".hpp" quand il s'agit de headers C++ pour les différencier des headers C, même si ".h" est tout à fait correct.

Ensuite à ce stade on ne peut pas utiliser string, on ne peut utiliser que std::string (car la classe string est déclarée dans la STL dans le namespace STL). Pour éviter d'avoir à préciser std::, on peut utiliser la directive "using namespace std;", mais c'est très peu recommandé (comprendre : très mal) de le faire dans un header.

Par ailleurs, vu que le nombre de candidats (et les autres valeurs stockées dans ta classe) sont toutes positives, il serait plus propre d'utiliser des "unsigned" (= "unsigned int") plutôt que des "int". Je passe sur les conventions de nommages qui ne sont pas cohérentes dans l'exercice (par exemple nbelecteurs au lieu de nbElecteurs).

Petite digression :

Si on était dans le monde réel on éviterait de manipuler std::string * pour stocker un ensemble de string. D'une part ce n'est pas très simple à manipuler (il faut l'allouer, le désallouer, le réallouer s'il est trop petit, en plus il faut stocker sa taille dans un unsigned), et d'autre part ce n'est pas très efficace (par exemple pour voir si un élément est dans le tableau, je dois dans le pire cas parcourir tout le tableau). Si l'énoncé ne l'imposait pas il serait beaucoup plus simple d'utiliser un std::set<std::string>. L'un des gros intérêts, c'est que copier un std::set dans un std::set (ou une std::list, ou un std::vector, plus généralement n'importe quel container fourni par la stl) se fait simplement avec l'opérateur =, comme tu le ferais avec un entier.
https://forums.commentcamarche.net/forum/affich-37604421-introduction-a-la-stl-en-c-standard-template-library

Ainsi dans la vraie vie on aurait écrit par exemple :

#include <set> 
#include <string> 

class Election { 
  protected: 
    //... 
    std::set<std::string> nomDesCandidats; 
  public: 
    election_t( 
      const std::set<std::string> & nomDesCandidats0 
    ): 
      nomDesCandidats(nomDesCandidats0) 
    {} 

    inline std::size_t getNbCandidats() const { 
      return this->nomDesCandidats.size(); 
    } 
}; 

int main() { 
  std::set<string> candidats; 
  candidats.insert("Marc"); 
  candidats.insert("Sophie"); 
  Election election(candidats) 
  return 0; 
}


Retour à l'exercice :

Du coup j'en viens à me demander si ton exercice ne se fait pas sans la STL (et donc une "string" est un "char *", donc tes électeurs sont stockées dans un char **). Dans le doute je note string_t ce type dans ce qui suit.

#include <string> 
#include <iostream> 

typedef std::string  string_t; 

int main() { 
    string_t * strings = new string_t[3]; 
    strings[0] = std::string("plop"); 
    strings[1] = std::string("plip"); 
    strings[2] = std::string("plap"); 
    for(std::size_t i = 0; i < 3; ++i) { 
        std::cout << strings[i] << std::endl; 
    } 
    return 0; 
} 


Pour faire une copie d'un tableau dans un autre, on pourrait être tenté d'utiliser un memcpy, ce qui serait la méthode la plus efficace si c'était par exemple un tableau int * (plus généralement un tableau d'objets qui ne stocke ni pointeur, ni référence). Mais là ça a neuf chance sur dix de rater, car la classe std::string encapsule sûrement des pointeurs et on court droit à la catastrophe si on fait ça.
http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/memcpy.3.html

Heureusement dans la STL, l'opérateur = existe pour std::string (pour copier une chaîne dans une autre) et donc ça va grandement simplifier les allocations qu'on aurait eu à faire en C.

int main() { 
    string_t * strings = new string_t[3]; 
    strings[0] = std::string("plop"); 
    strings[1] = std::string("plip"); 
    strings[2] = std::string("plap"); 
    for(std::size_t i = 0; i < 3; ++i) { 
        std::cout << strings[i] << std::endl; 
    } 

    string_t * strings2 = new string_t[3]; 
    for(std::size_t i = 0; i < 3; ++i) { 
        strings2[i] = strings[i]; 
        std::cout << strings2[i] << std::endl; 
    } 
    return 0; 
} 


Bonne chance
0