IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Petit problème avec mon constructeur spécifique


Sujet :

C++

  1. #1
    Membre éprouvé
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Points : 1 277
    Points
    1 277
    Par défaut Petit problème avec mon constructeur spécifique
    Bonsoir tout le monde,

    J'ai un petit problème avec mon constructeur spécifique.

    voici tout d'abord le constructeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CVoiture::CVoiture(const char* UneImmatriculation,short UnNombreDePlace,double UnVolumeTransportableDeMarchandise)
    :Vehicule3(UneImmatriculation),Vehicule3(UnNombreDePlace),m_VTM(0.0)
    {
    	VTM(UnVolumeTransportableDeMarchandise);
    }
    et voici les messages d'erreur :

    error C2664: '__thiscall Vehicule3::Vehicule3(const class Vehicule3 &)' : cannot convert parameter 1 from 'short' to 'const class Vehicule3 &'
    Reason: cannot convert from 'short' to 'const class Vehicule3'

    No constructor could take the source type, or constructor overload resolution was ambiguous
    et le second qui est un peu plus clair :
    error C2437: 'Vehicule3' : already initialized
    Voici le .h de CVoiture :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class CVoiture : public Vehicule3
    {
    public:
    	CVoiture();
    	CVoiture(const CVoiture& Modele);
    	CVoiture(const char* UneImmatriculation,short UnNombreDePlace,double UnVolumeTransportableDeMarchandise);
    	~CVoiture();
     
    	bool		VTM(double UneValeurTransportableDeMarchandise);
     
    private:
    	double		m_VTM; //Volume transportable de marchandise
     
     
    };
    et voici le .h de Vehicule 3 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Vehicule3
    {
    public:
     
    	Vehicule3();
    	Vehicule3(const Vehicule3& Modele);
    	~Vehicule3();
     
     
     
    	bool		Immatriculation(const char* UneImmatriculation);
     
    private:
    	CChaine		m_Immatriculation;
    	short		m_NombreDePersonnes;
     
     
     
    };

    et enfin, voici le cpp entier dans lequel il y'a les deux erreurs :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    #include <BasicConsole.h>
    #include "vehicule3.h"
    #include "chaine.h"
     
     
    Vehicule3::Vehicule3()
    :m_Immatriculation(""),m_NombreDePersonnes(0)
    {
    }
     
    Vehicule3::Vehicule3(const Vehicule3& Source)
    :m_Immatriculation(Source.m_Immatriculation),m_NombreDePersonnes(Source.m_NombreDePersonnes)
    {
    }
     
    Vehicule3::~Vehicule3()
    {
    }
     
    CVoiture::CVoiture()//constructeur par défaut
    :m_VTM(0.0)
    {
    }
     
    CVoiture::CVoiture(const CVoiture& Source) //constructeur par copie
    :Vehicule3(Source),m_VTM(Source.m_VTM) //une question que je me pose, est-ce que Vehicule3(Source) contient tous les membres de Véhicules3 ?
    {
    }
     
    CVoiture::CVoiture(const char* UneImmatriculation,short UnNombreDePlace,double UnVolumeTransportableDeMarchandise)
    :Vehicule3(UneImmatriculation),Vehicule3(UnNombreDePlace),m_VTM(0.0)
    {
    	VTM(UnVolumeTransportableDeMarchandise);
    }
     
    CVoiture::~CVoiture()
    {
    }
     
    bool CVoiture::VTM(double UneValeurTransportableDeMarchandise)
    {
    	if(UneValeurTransportableDeMarchandise <= 0.0) return false;
    	m_VTM = UneValeurTransportableDeMarchandise;
    	return true;
     
    }
     
    CTabVoitures::CTabVoitures()
    :m_Nombre(0),m_Tableau(NULL)
    {
    }
     
    CTabVoitures::~CTabVoitures()
    {
    }
     
    CLeTout::CLeTout()
    {
     
    }
     
    CLeTout::~CLeTout()
    {
     
    }
     
     
     
    bool CLeTout::FctnTraiterLigne(const CChargeurFichierTexte& CC, void* Contexte)
    {
    	return ((CLeTout*)Contexte)->TraiterLigne(CC);
    }
     
     
     
    bool CLeTout::Charger(const char* NomFichier) //copie telle quelle
    {
    	CChargeurFichierTexte	Chargeur;
     
    	/*chargeur.Charger, je lui passe le nom du fichier et le contexte et il faudra aussi lui 
    	  passer le séparateur de caractère qui est utilisé par la méthode "Définir" de la classe 
    	  "CChaineComposée" et il faut aussi lui passer en plus du contexte la fonction qu'il doit 
    	  appeler, ça sera "FctnTraiterLigne", ici je lui passe l'adresse de cette fonction là.*/
    	return Chargeur.Charger(NomFichier,'\t',CLeTout::FctnTraiterLigne,this);
    }
     
    bool CLeTout::TraiterLigne(const CChargeurFichierTexte& CC)
    {
    	if (strlen(CC.Champs(0)) == 1) switch (CC.Champs(0)[0])
    	{
    		case 'V':
    			//if (CC.NombreChamps() == 3) m_TV.Ajouter(CVoiture(CC.Champs(1),atof(CC.Champs(2)),atof(CC.Champs(3))));
    			break;
    	}
    	return true;
    }
    Le problème doit venir du fait qu'il croit que Vehicule3 est déclaré deux fois mais il me semble que ce n'est pas le cas ?

    Merci d'avance pour votre aide.

    beegees

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    Le but des listes d'initialisation est... d'appeler les constructeurs qui vont bien.

    Ainsi, si ta voiture est un Véhicule, et que pour initialiser un véhicule, tu dois fournir une immatriculation et un nombre de place, il faut que tu crées un constructeur de Véhicule qui prend ces deux éléments, et que tu utilise ce constructeur particulier dans la liste d'initialisation.

    Ainsi, le constructeur de Vehicule3 ne peut pas prendre la double forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Vehicule3 (const char*); /* et un autre constructeur */
    Vehicule3(short);
    mais doit prendre la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Vehicule3 (const char*, short);
    Et, dans le constructeur de ta voiture, il sera alors appelé sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CVoiture::CVoiture(const char* UneImmatriculation,short
              UnNombreDePlace,double UnVolumeTransportableDeMarchandise)
              :Vehicule3(UneImmatriculation, UnNombreDePlace)
    {
    }
    Ensuite, il est inutile d'initialiser m_VTM à une valeur, si c'est pour, par la suite, appeler une méthode qui va changer cette valeur.

    C'est toute la beauté des liste d'initialisation, que de permettre d'initialiser de manière tout à fait identique les types personnalisés (structures ou classes) et les types primitifs, car il existe des "pseudo constructeurs" pour ces derniers.

    Au final, ton constructeur de voiture devient donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CVoiture::CVoiture(const char* UneImmatriculation,short 
              UnNombreDePlace,double UnVolumeTransportableDeMarchandise)
              :Vehicule3(UneImmatriculation, UnNombreDePlace),
              m_VTM(UnVolumeTransportableDeMarchandise)
    {
       //remarque qu'il n'y a plus rien à faire ici :D
    }
    Ceci dit, je ne peux m'empêcher d'insister encore une fois sur le conseil très important de préférer les classes du C++ aux capacités issues du C (la std::string, qu'il vaut mieux préférer aux chaines de caractères C style en l'occurrence).

    Enfin, si on insiste sur le besoin d'utiliser des noms explicites pour les noms de variables et d'arguments, il y a malgré tout une certaine mesure a adopter dans le sens où les noms de variables et d'arguments trop longs ont réellement tendance à compliquer la lecture (et surtout l'utilisation de ces noms), ce qui nuit au final à l'objectif même d'une politique stricte de choix explicites de noms.

    En effet, si une variable i est facile à retenir, on peut lui reprocher de manquer cruellement de "précision".

    Par contre, si un nom de variable du genre de UnNombreDePlace a l'avantage d'être claire sur le but de la variable, la lecture devient rapidement difficile, et l'utilisation de cette variable devient rapidement peut instinctive (pense qu'il suffit d'une faute d'orthographe ou d'une majuscule manquante pour que le langage ne reconnaisse pas l'identifiant )

    Ainsi, l'idéal est quand même de trouver le juste milieu entre ces deux extrèmes, et un nom du genre de NbPlace représente à mon sens un bon compromis

    Enfin, et c'est de manière tout à fait générale, il n'y a, a priori, aucune raison pour que tous tes mutateurs renvoient un booléen...

    L'habitude est même plutôt de ne rien leur faire renvoyer, éventuellement, en faisant précéder le nom de la fonction par le terme set.

    La méthode bool VTM(double UneValeurTransportableDeMarchandise); serait donc avantageusement modifiée en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void setVTM(double MaxTransport);
    Mais le volume maximal transportable n'a aucune raison - a priori - d'être modifié une fois que le véhicule a été créé (comment voudrais tu - à bien y réfléchir - arriver à faire tenir le volume que tu peux mettre dans un camion dans une mini ) la méthode n'a même pas besoin d'exister

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Autre chose, je souhaiterais attirer ton attention sur la nécessité de choisir correctement les unités utilisées pour représenter les différentes valeurs, et, le type qui découle de ces choix.

    En effet, il faut savoir que tous les nombres à virgule flottantes (qu'il s'agisse de float ou de double) présentent certains problèmes de précision, qui sont principalement dus à la manière dont les valeurs sont représentées en mémoire.

    Ainsi, je te conseillerais fortement d'envisager de représenter le volume maximal transportable en nombre de litres, plutôt qu'en nombre de mètres cubes.

    Cela te permettra de représenter la valeur sous la forme d'entiers (int) au lieu de sous la forme de nombre à virgule flottante (float ou double), et te permettra par conséquent de contourner une grosse partie des problème inhérents aux réels...

  4. #4
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 861
    Points
    11 861
    Par défaut
    Je te conseille de lire la FAQ (section "Classes") en complément du post de koala01.

  5. #5
    Membre éprouvé
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Points : 1 277
    Points
    1 277
    Par défaut
    Salut Koala,

    Un grand merci pour ta réponse.

    Ce message répond à une partie de ton message, je répondrai au reste juste après :

    Le but des listes d'initialisation est... d'appeler les constructeurs qui vont bien.
    Donc des constructeurs qui existent je présûme ?


    Ainsi, si ta voiture est un Véhicule, et que pour initialiser un véhicule, tu dois fournir une immatriculation et un nombre de place, il faut que tu crées un constructeur de Véhicule qui prend ces deux éléments, et que tu utilise ce constructeur particulier dans la liste d'initialisation.
    Car je présûme qu'autrement on a pas tous les éléments de la voiture, si je ne met pas les membres de la classe Vehicule3, ma voiture ne sera jamais complète.

    Quand tu parles de liste d'initialisation, s'est bien ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    :Vehicule3(UneImmatriculation, UnNombreDePlace)

    S'est grâce à la liste d'initialisation que le compilateur sait quel constructeur il doit appeler ?

    Ce qui me trouble, s'est que l'on a ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CVoiture::CVoiture(const char* UneImmatriculation,short
              UnNombreDePlace,double UnVolumeTransportableDeMarchandise)
    au dessus et ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     :Vehicule3(UneImmatriculation, UnNombreDePlace)
    en dessous.

    Une autre question :

    Puis-je me permettre dans le point h de mettre ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Vehicule3::Vehicule3(const char*,short)
    {
    }
    donc pas de nom de variable

    et dans le point cpp ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Vehicule3::Vehicule3(const char* UneImmatriculation,short)
    {
    }
    là par exemple le nom d'une variable ?

    J'ai lu ce matin que le compilateur s'en fichait des noms de variables mais qu'il se préocupait plus de la signature de la fonction, s'est à dire le type des paramètres entrants.

    J'ai fais un copié collé de ton code, ça fonctionne, mais je vais essayer de comprendre en relisant ton message.

    Je répondrai à la suite après.

    Merci encore pour tout.

    beegees

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Excuses mon retard, j'ai été fort occupé aujourd'hui...
    Citation Envoyé par beegees Voir le message
    Donc des constructeurs qui existent je présûme ?
    Oui, bien sur... autrement le compilateur va t'envoyer sur les roses

    Sois bien attentif au fait que:
    • Tu ne peux appeler qu'une seule fois le constructeur par élément à initialliser
    • le constructeur doit être déclaré dans la définition de la classe (sinon c'est le compilateur qui se plaindra)
    • Le constructeur doit être implémenté (sinon, c'est l'éditeur de liens qui se plaindra)

    Car je présûme qu'autrement on a pas tous les éléments de la voiture, si je ne met pas les membres de la classe Vehicule3, ma voiture ne sera jamais complète.
    Heuuu... oui, mais non...
    En fait, il y a deux problèmes:

    Le premier est que, si tu n'indique pas au compilateur les données qu'il doit fournir au constructeur des membres (ou de la/des classe(s) de base), il ne saura jamais les déterminer lui-même...

    Il sera donc incapable d'appeler le constructeur du membre (ou de la classe de base), et on arrive en effet à un type qui ne peut pas être complet.

    Un autre problème est qu'il peut malgré exister un constructeur que le compilateur puisse prendre en compte: un compilateur qui ne nécessite aucun argument obligatoire (soit parce qu'il ne demande tout simplement aucun argument, soit parce qu'il attend des arguments disposant tous de valeur par défaut).

    Si un tel constructeur existe et que tu ne précise pas au compilateur lequel des deux il doit appeler, c'est d'office celui-là sans argument qu'il choisira , et ce, même si un autre constructeur sans doute plus adapté et demandant des argument existe (parce que, comme indiqué plus haut, il ne sera pas en mesure de déterminer la valeur à passer en argument )

    Ainsi, si tu as un moteur, que, pour la facilité, nous considérons comme défini par une cylindrée (en cc) et une puissance (en cv), toutes les deux exprimées sous la forme d'entier, tu pourrais très bien décider d'avoir un constructeur sans argument obligatoire qui construirait d'office un moteur de 4500cc et de 675cv (ca, ca doit au moins être un moteur de porche )

    Il pourrait prendre au choix la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Moteur(int cyl =4500, int puis = 675)
    //implémenté sous la forme de
    Moteur::Moteur(int cyl, int puis):cylindr(cyl),puiss(puis)
    {
    }
    ou de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Moteur();
    //implémenté sous la forme de
    Moteur::Moteur():cylindr(4500),puiss(675)
    {
    }
    Seulement, voilà, la voiture que tu veux construire, c'est une mini...

    Sa cylindrée est de 950cc et sa puissance flirte tout juste avec les 60cv...

    Et, manque de bol, tu ne précise pas le constructeur pour le moteur.

    Au final, tu te retrouvera donc avec une mini ayant un moteur de 4500cc et une puissance de 675 cv (Je mets quiconque au défit de maitriser cet engin de mort )

    Donc, au final, si tu ne précise pas les constructeurs de tous les membres et de toutes les classes dérivées, tu te retrouvera soit avec un objet qui n'est pas complet (mais le compilateur se plaindra) soit avec un objet... qui ne correspond pas à ce que tu attend (et pour lequel le compilateur ne se plaindra pas).
    Quand tu parles de liste d'initialisation, s'est bien ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    :Vehicule3(UneImmatriculation, UnNombreDePlace)
    Exactement.

    Elle commence par : après avoir fourni le prototype du constructeur, contient l'ensemble des constructeurs des membres et des classes de base, séparés par une virgule, et s'arrête juste avant l'accolade ouvrante indiquant le début de la fonction.
    S'est grâce à la liste d'initialisation que le compilateur sait quel constructeur il doit appeler ?
    Oui, ainsi que l'ordre dans lequel il doit les appeler...

    S'il est correctement réglé, et que tu les appelle dans un mauvais ordre, il devrait te le signaler par un avertissement du genre de
    ||=== Nom_Projet ===|
    chemin_vers\fichier.cpp||In constructor 'Nom_Classe::Nom_classe(liste des arguments)': |
    chemin_vers\fichier.cpp|num_ligne|warning: 'Nom_Classe::membre' will be initialized after|
    chemin_vers\fichier.cpp|num_ligne|warning: 'type_autre_membre Nom_Classe::autre_membre'|
    chemin_vers\fichier.cpp|num_ligne|warning: when initialized here|
    ||=== Build finished: 0 errors, 3 warnings ===|
    qui signifie à peu près
    attention: dans le constructeur (prototype du constructeur), 'tel membre' sera initialisé apres 'tel autre membre' quand il est initialisé ici
    Ce qui me trouble, s'est que l'on a ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CVoiture::CVoiture(const char* UneImmatriculation,short
              UnNombreDePlace,double UnVolumeTransportableDeMarchandise)
    au dessus et ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     :Vehicule3(UneImmatriculation, UnNombreDePlace)
    en dessous.
    Ca, c'est du à mon habitude (idiote )qui consiste à limiter autant que possible la largeur de mes codes à 80 colonnes...

    L'un des concepts de base en programmation est qu'un code est beaucoup plus souvent lu par l'humain qu'il n'est parcouru par (ici) le compilateur...

    Il faut, bien sûr, que le code explique clairement au compilateur ce que tu attend de lui, mais sa première qualité est d'être facilement lisible par le type qui se trouve face à son écran...

    Historiquement, (et je parle ici d'un temps où on n'envisageait sans doute même pas qu'il puisse un jour y avoir un écran et un clavier à un ordinateur, qui, de toutes manières, était suffisemment grand pour ne même pas savoir être placé chez moi), la limite du nombre de caractères par ligne de code était de 80.

    Ce nombre restreint de caractères a l'énorme avantage d'être facilement imprimable (quelle que soit l'imprimante) et affichage (y compris sur les écrans ayant les plus faibles résolutions.

    Le C++ autorise beaucoup plus de caractères sur une ligne logique (la norme impose un minimum de 65 535 caractères), mais une ligne d'une telle taille est, tu t'en doutes surement, parfaitement illisible pour l'homme.

    J'ai donc pris l'habitude (et je ne suis pas le seul, pour tout dire) de limiter mes lignes de code à 80 caractères... C'est aussi simple que cela (même si l'explication a été longue )
    Une autre question :

    Puis-je me permettre dans le point h de mettre ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Vehicule3::Vehicule3(const char*,short)
    {
    }
    donc pas de nom de variable

    et dans le point cpp ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Vehicule3::Vehicule3(const char* UneImmatriculation,short)
    {
    }
    là par exemple le nom d'une variable ?

    J'ai lu ce matin que le compilateur s'en fichait des noms de variables mais qu'il se préocupait plus de la signature de la fonction, s'est à dire le type des paramètres entrants.
    Soit très attentif au fait qu'une fonction (qu'il s'agisse d'une fonction libre ou d'une méthode de classe) ne peut être implémentée qu'une et une seule fois...

    Tu ne peux donc avoir qu'une et une seule fois la paire d'accolade après le prototype de la fonction.

    Si tu définis (== implémente ou donne le corps de) la fonction dans le .cpp sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Vehicule3::Vehicule3(/*liste d'argument*/)
    {
    }
    tu peux (c'est autorisé) décider de ne pas nommer un argument.

    Cependant, tout argument non nommé est d'office inutilisable (même si il a été nommé dans la déclaration de la fonction qui se trouve dans le fichier d'en-tête)...

    Tu va sans doute te demander quel est alors le but de déclarer un argument sans le nommer.

    Le fait est que, si tu ton compilateur est correctement réglé, et que tu fournis un argument (ou que tu déclare une variable) que tu n'utilise jamais, il te lancera un avertissement du genre "tel nom n'est jamais utilisé".

    Le fait de ne pas donner le nom de l'argument permet d'éviter cet avertissement.

    C'est intéressant s'il se fait qu'une fonction doit lancer une exception (ou renvoyer une valeur bien précise) de manière inconditionnelle (et sans doute parce qu'elle est redéfinie dans une classe mère ou dérivée)

    Si tu défini la fonction dans le fichier d'en-tete (c'est à dire: le fichier ".h", bien que l'extension soit ici tout à fait libre ), cela se fait donc sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class MaClass
    {
        /*...*/
        void lafonction(/* arguments */)
        {
            /*...*/
        }
    };
    et la fonction ne peut pas être redéfinie de manière classique dans le fichier *.cpp...

    Les règles en ce qui concerne les noms des arguments sont exactement identiques, avec exactement les même conséquences.

    Si tu déclares (c'est à dire que tu dis juste au compilateur que la fonction existe) seulement la fonction, cela se fait sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class MaClass
    {
        /*...*/
        void lafonction(/* arguments */);/* pas d'accolades, mais un ";" après la
                                          * parenthèse ;)
                                          */
    };
    le compilateur ne regardera effectivement que le type et le nombre des arguments...

    Tu es donc tout à fait libre de décider d'indiquer le nom... ou de ne pas le faire.

    Mais on en revient encore une fois à notre sacrosaint principe de la "lisibilité" du code.

    En effet, il faut bien comprendre que, à l'exception de la personne qui va écrire le code qui implémente les différentes fonctions/méthodes, le fichier d'en-tête est le seul fichier qui sera accessible à tous (et c'est d'ailleurs ce fichier que tu ouvrira si tu hésite sur les arguments à fournir à une fonction)...

    Il faut donc veiller à ce que le fichier fournisse au minimum au lecteur suffisemment d'informations pour lui permettre de savoir quelle valeur il est sensé passer à la fonction pour lui permettre de faire correctement son travail.

    Cette règle est très floue, et c'est voulu.

    En effet, si tu as une fonction du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void setNomDeFamille(const std::string&);
    tu te rend compte que le fait de fournir le nom de l'argument (qui serait bien nouveauNomFamille, par exemple ) n'apporte pas vraiment d'informations supplémentaire au lecteur

    Par contre, si tu as une fonction du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void laFonctionQuiFaitBrol(const std::string&, const std::string&, int, int);
    tu te rends tout aussi vite compte que, même si on remplace QuiFaitBrol par une action particulière, le fait de donner les noms des arguments est de nature à faciliter la compréhension du lecteur, ne serait-ce que pour qu'il sache dans quelle ordre fournir les deux chaines et dans quel ordre fournir les deux entiers...
    J'ai fais un copié collé de ton code, ça fonctionne, mais je vais essayer de comprendre en relisant ton message.

    Je répondrai à la suite après.

    Merci encore pour tout.

    beegees
    Fais bien à ton aise... d'autant que j'ai encore une fois écrit un véritable roman

Discussions similaires

  1. [débutant] Un petit problème avec mon code
    Par Muesko dans le forum Débuter
    Réponses: 3
    Dernier message: 28/08/2008, 17h12
  2. petit problème avec mon switch
    Par beegees dans le forum C++
    Réponses: 2
    Dernier message: 03/05/2008, 19h52
  3. Petit problème avec le constructeur par copie
    Par beegees dans le forum C++
    Réponses: 16
    Dernier message: 01/04/2008, 16h34
  4. [MySQL] Divers petits problèmes avec mon script
    Par fourniey dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 26/12/2007, 16h20
  5. Un tout petit problème avec mon menu contextuel
    Par jbrasselet dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 05/10/2007, 15h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo