Votre message ne comporte pas ou peu de formules de politesse (« Bonjour », « Merci », « Au revoir », etc.). Les règles du site exigent que chaque nouveau message comporte un minimum de politesse. Après tout, les gens qui répondent le font gratuitement, sur leur temps libre. Ils méritent bien un minimum de considération, n'est-ce pas ?
Manque de précisions
Vous êtes ici sur un forum d'entraide communautaire et non pas sur un forum de demande de service, le but n'est donc pas de fournir une réponse toute faite ou de directement fournir la solution à quiconque viendrait sans la moindre trace. Afin d'obtenir de l'aide et une solution à votre problème, il est fortement recommandé de présenter clairement l'état actuel du problème en nous fournissant :
Un descriptif clair et précis du problème
La tentative actuelle de résolution que vous avez effectué
Le résultat attendu et le résultat actuel
Toutes pistes de recherches pouvant aider à la résolution
Mauvais titre
Le titre est un élément important qui ne doit pas être négligé. N'oubliez pas cette règle simple : le titre idéal résume la question que vous allez poser en une petite phrase. Il doit permettre aux visiteurs de se repérer facilement dans le forum visité et d'identifier le sujet à sa seule lecture.
Vous pouvez utiliser divers préfixes comme [Erreur], [MySQL], [Compatibilité], etc... Aussi, pensez à consulter les règles propres à chaque forum (visibles dans les topics épinglés en haut des sections).
De plus, choisir un bon titre permet de rendre plus faciles les recherches des autres membres.
Les titres de type "besoin d'aide" ou "problème" ne sont pas tolérés.
Pour modifier votre titre, éditez le premier message de votre sujet.
(titre originel : problème de c++)
Pas d'aide concernant le code par MP, le forum est là pour ça :)
Alors, déjà, tu vas nous faire le plaisir de virer cette odieuse directive using namespace std, que nous ne pourrions voir.
Cette directive a été fournie lors de la standardisation de 1998, lorsque le comité a décidé de faire passer la bibliothèque standard dans l'espace de noms std, pour permettre au code qui existait déjà de continuer à fonctionner "sans trop de changements".
On peut difficilement estimer que le code que l'on écrit aujourd'hui, au début de l'année 2020, soit du code "écrit avant 1998", et ce, d'autant plus que quatre évolutions de la norme ont sont arrivées entre temps
Ensuite, tu vas nous faire le plaisir d'utiliser la classe std::string pour représenter le nom, Cela te simplifiera énormément la vie en t'évitant, justement, d'avoir à définir par toi-même le ccnstructeur de copie et le destructeur.
Note au passage que tu as oublié de définir l'opérateur d'affectation, qui est la troisième partie requise par la fameuse règle appelée "Big three rule" ;). Renseigne toi sur le patron "copy and swap" pour mettre tout cela en musique.
Cet oubli est sans doute la cause du problème que tu rencontre avec la ligne de code Automate usagee=Automate("Allen Bradley",2019)=Schneider;.
Enfin, le compilateur ne peut que t'envoyer bouler lorsqu'il rencontre la ligne de code cout<<usagee.nom<<endl;, parce que tu as expressément placé la donnée nom dans l'accessibilité privée, ce qui fait que cette donnée n'est accessible qu'au fonctions membres de ta classe.
Ah, et, au passage: ta fonction affiche devrait être déclarée comme étant une fonction membre constante, de manière à préciser au compilateur qu'elle s'engage à ne pas modifier l'état de l'instance de ta classe.
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
Automate::Automate(char*cp,int x=2000)
// on attend donc une séquence de caractères terminée par un \0 que l'on VA MODIFIER, et une année facultative
// sauf qu'on risque de lui passer une séquence non modifiable comme "M580" => erreur!
{
nom = new char[strlen(cp)+1];
// utiliser new c'est s'attendre à un problème certain
// à moins d'être un expert dans la "règle des 3"
// devenue depuis 2011 la "règle des 5".
x=annee;
// ne serait-ce pas plutôt x à copier dans année?
strcpy(cp,nom);
// strcpy est clairement une fonction C!
cout<<"ceci est le premier message"<<endl;
}
Merci de tenir compte de mon message : on n'a toujours pas plus d'infos sur ce qui se passe (ou ne se passe pas), le titre est toujours aussi vague, et le code est illisible (utilise le bouton </> de la barre d'outils du forum pour poster du code coloré).
Pas d'aide concernant le code par MP, le forum est là pour ça :)
Et dans la definition de ce constructeur tu reecris
Automate::Automate(char*cp,int x=2000)
Dans le prototype d'en haut tu aurais pu te passer de cette initialisation.
Je sais pas si j'ai compris le log d'erreurs mais annee est tout d'abord un attribut de Automate....essaie de changer le nom de ce parametre, ou alors ne mets aucun nom dans la classe.
L'erreur a ta ligne 34 est plus que normale. Tu as ecris
Automate::Automate:void affiche()
au lieu de
void Automate::affiche()
La ligne où tu as ecris
cout<<usagee.nom<<endl;
dans ton main() signale aussi une erreur parceque nom est un attribut privé: soit tu crees un accesseur ou tu rend cet attribut publique pour l'utiliser...et c'est meme un pointeur, donc meme si il etait publique, tu aurais du ecrire
Non surtout pas le cours C++ d'Openclassrooms. Il est mauvais.
Il est mauvais a quel niveau precisement? J'ai suivi ce cours pendant un moment, et y'avais pas de contradictions avec celui de l'ecole ou des supports....
La, j'ai rien a rajouter. Le cours d'openclassrooms est vachement vieux a la vue de l'evolution du C++...
Ces notions la, je pensais pas que c'etait mauvais: je trouvais cela un peu derriere par rapport a certains cours mais je me disais que c'etait pour faciliter la tache du novice. Merci
Donne donc un meilleur cours a cet homme qui a un souci, il doit relire le cours
Non surtout pas le cours C++ d'Openclassrooms. Il est mauvais.
Il est mauvais a quel niveau precisement? J'ai suivi ce cours pendant un moment, et y'avais pas de contradictions avec celui de l'ecole ou des supports....
C'est sans doute parce que le cours donné à l'école est aussi mauvais que celui d'openclassrooms
Je ne vais pas répéter une fois de plus tous les points qui font que ce cours est mauvais. Une simple recherche sur ce forum permettra de trouver les raisons.
Mais saches qu'il vous apprend quelque chose qui est plus proche du C with classes, mais qu'il contient carrément des erreurs et qu'il vous donne de très mauvaises habitudes. Même les exemple, en POO, par exemple, sont particulièrement mauvais
De plus, il faut savoir que C++ a beaucoup évolué ces dernières années: depuis 2011, il y a eu trois (presque quatre) évolutions majeures de la norme en 2011, 2014 et 2017 (la quatrième sera finalisée cette année), et que ces évolutions font que l'on ne développe plus du tout en C++ comme on le faisait "avant".
Or, le cours tel qu'il est donné ressemble à la manière dont on envisageait le C++ en 1995.
Asmitta a écrit:
Dans ta classe tu ecris
Automate(char*nom,int annee=2000);
Et dans la definition de ce constructeur tu reecris
Automate::Automate(char*cp,int x=2000)
Dans le prototype d'en haut tu aurais pu te passer de cette initialisation.
C'est même pire: outre le fait que les noms de paramètres ne correspondent pas (ce qui n'est pas un problème en soit tant que l'on n'utilise pas de valeur par défaut), on ne peut pas redéfinir la valeur par défaut au niveau de l'implémentation lorsqu'elle a été définie dans la déclaration.
Asmitta a écrit:
La ligne où tu as ecris
cout<<usagee.nom<<endl;
dans ton main() signale aussi une erreur parceque nom est un attribut privé: soit tu crees un accesseur ou tu rend cet attribut publique pour l'utiliser...et c'est meme un pointeur, donc meme si il etait publique, tu aurais du ecrire
cout<<usagee->nom<<endl;
Hé beé... non, justement, parce que usagee n'est pas un pointeur...
C'est nom qui est un pointeur, ce qui est normal, vu qu'il doit permettre la représentation d'une chaine de caractères
ISLEMKRID a écrit:
@koala01 merçi pour votre réponse mais je n'ai pas bien saisi ce qu'il faut faire
Voici le code tel qu'il devrait être
Automate.hpp
/* on crées des "include guards" pour éviter les définitions
* multiple de la classe
*/
#ifndef AUTOMATE_HPP
#define AUTOMATE_HPP
#include <string>
class Automate{
public:
Automate(std::string const & n, int a = 2000);
void affiche() const;
/*!!! ET C'EST TOUT !!!*/
private:
std::string nom;
int annee;
};
#endif // AUTOMATE_HPP
Tu auras remarqué
que je n'utilise pas char * pour représenter le nom, mais que j'utilise la classe std::string qui est spécifiquement prévue pour représenter des chaines de caractères
que je n'utilise pas la directive using namespace std; (et surtout pas dans un fichier d'en-tête!!!): à la place, j'ai utilisé le nom pleinement qualifié (std::string au lieu de string)
que je n'ai eu besoin de déclarer ni le constructeur de copie, ni l'opérateur d'affectation, ni le destructeur
je n'ai pas inclus le fichier <iostream> ici
j'ai déclaré la fonction affiche comme étant une fonction membre constante de la classe (qui s'engage à ne pas modifier l'instance de la classe en cours lorsqu'elle est appelée.
La principale raison du (3), c'est que le compilateur créera automatiquement ces trois éléments en leur donnant un comportement par défaut) si je ne lui donne pas une bonne raison de ne pas le faire (par exemple, en les définissant moi-mêm), et que les comportement par défaut me suffisent amplement, vu que j'ai utilisé une std::string pour représenter la donnée membre nom (et que la donnée membre annee est un type primitif)
si j'essaye de copier la classe Automate, il devra copier la donnée nom et la donnée annee, mais il sait comment le faire
si j'essaye d'effectuer d'assigner une instance de Automate, il devra assigner la donnée nom et la donnée année de l'une à l'autre, et il sait comment le faire
quand il est temps de détruire une instance de Automate, il devra détruire la donnée nom et la donnée année, mais saurat comment le faire.
Avoue que ca facilite grandemen la tâche par rapport à l'utilisation d'un char * non?
Et comme la classe std::string (std::basic_string<char>, en réalité) fait partie de la bibliothèque standard, tu as la certitude que n'importe quel compilateur fourni après 1998 fournit cette classe.
La principale raison du (4) est que l'on veille toujours à n'inclure que le stricte minimum requis, surtout au niveau des fichiers d'en-tête. Comme je n'ai pas besoin des fonctionnalités offertes par iostream au niveau du fichier d'en-tête, je ne l'inclus pas.
La principale raison du (5) est que cette fonction affiche devra être utilisable y compris lorsque je serai face à une instance déclarée comme étant constante, et que l'idée est de déclarer comme étant constante toutes les données qui n'ont pas vocation à être modifiée dans un contexte donné. Cela permet d'éviter bien des erreurs
Voyons maintenant l'implémentaiton des fonctions de cette classe
Le fichier Automate.cpp
/* le compilateur doit connaitre la classe Automate */
#include <Automate.hpp>
/* Pour implémenter la fonction affiche, j'aurai besoin
* de connaitre std::cout. J'inclus donc <iostream> ici
*/
#include <iostream>
Automate::Automate(std::string const & n, int a):
nom{n},annee{a}{
}
void Automate::affiche() const{
std::cout<<"Automate :\n"
<<"\t nom : "<<nom<<"\n"
<<"\t annee : "<<annee<<"\n";
}
(j'ai un peu modifié le format de l'affichage par rapport à ton code, je le trouve plus pratique sous cette forme :D)
Tu remarqueras que j'ai utilisé la liste d'initialisation pour définir les valeurs de nom et de annee. C'est la manière qu'il faut utiliser, à moins que tu n'aies vraiment une bonne raison pour ne pas le faire. D'autant plus qu'il y a quelques situations dans lesquelles tu n'auras pas le choix
Tu remarquera aussi que j'ai utilisé les symbole { et } pour définir les valeurs de nom et de annee. C'est l'une des "nouvelles fonctionnalités" apparues en 2011 : Alors que les accolades { et } ne pouvaient être utilisées que pour les tableaux de taille fixe avant cette évolution, elles peuvent désormais êtres utilisées pour n'importe quelle initialisation, et nous les utilisons donc partout ;).
Tu remarqueras que je n'ai toujours pas utilisé la directive using namespace std;. C'est parce que j'ai écrit ce code en 2020, et que je ne peux donc décemment pas prétendre qu'il date ... d'avant la normalisation de 1998.
De plus, l'utilisation des espaces de noms permet d'éviter bien des soucis -- je t'expliquerai pourquoi et comment si tu en fais la demande -- et l'utilisation de la directive using namespace ne présente qu'un avantage minime par rapport aux problèmes qu'elle occasionne. Cela m'oblige, bien sur, à utiliser le nom pleinement qualifié std::cout, mais ce n'est a priori pas un problème
Par contre, tu remarqueras également que je n'ai pas utilisé sd::endl pour les retours à la ligne: j'ai utilisé le caractère échappé "\n". Le fait est que le retour à la ligne effectué par std::endl n'est, en quelque sorte, qu'un "effet secondaire" parce que std::endl sert essentiellement à purger le tampon du flux utilisé.
Même s'il est très intéressant d'utiliser std::endl dans certaines circonstances, il n'y a -- a priori -- aucun avantage à l'utiliser lorsque c'est inutile. Cela présente même plutôt un inconvénient dans la plupart des situations. J'ai donc pris l'habitude de ne presque jamais utiliser std::endl
Voyons enfin la fonction main
main.cpp
#include <Automate.hpp>
int main(){
/* déclare une fonction mommée Siemens ne prenant aucun
* paramètre et renvoyant une donnée de type Automate.
* Aucun intérêt ici
Automate Siemens();
*/
/* crée l'automate Schneider */
Automate Schneider{"M580",2017};
/* crée une copie de Schneider nommée Schneider1 */
Automate Schneider1{Schneider};
/* Qu'espères-tu faire exactement ici???
Automate usagee=Automate("Allen Bradley",2019)=Schneider;
* Si tu veux forcer l'utilisation de l'opérateur d'assignation
* tu dois travailler en deux fois:
*/
Automate usagee{"Allen Bradley", 2019}; // on crée l'automate
usagee = Schneider; // on assigne les donnée de Schneider
// à l'automate usagee
usagee.affiche(); // on observe le résultat
/* On ne peut pas accéder directement à usagee.nom
* car nom est dans l'accessibilité privée
cout<<usagee.nom<<endl;
*/
return 0;
}
Si tu veux pouvoir accéder à la donnée membre nom pour pouvoir l'afficher, il faudra fournir une fonction qui permette d'y acdéder, et que l'on appelle couremment un "accesseur" (par exemple une fonction getNom() ).
Seulement, tu ne peux envisger de fournir un accesseur que si le fait de fournir cette information correspond effectivement à un service que tu es en droit d'attendre de la part de la classe que tu développe.
Tu as de la chance, car, dans le cas de la classe Automate, on peut -- effectivement -- considérer le fait d'être en mesure de répondre à la question "quel est ton nom" correspond à un service que l'on est en droit d'attendre de sa part. Mais un tel service n'aurait aucun sens, par exemple, pour le réservoir à carburant d'une classe Vehicule.
Nous allons donc devoir modifier la classe pour lui donner une forme proche de
Automate.hpp
#ifndef AUTOMATE_HPP
#define AUTOMATE_HPP
#include <string>
class Automate{
public:
Automate(std::string const & n, int a = 2000);
void affiche() const;
std::string const & getNom() const;
/*!!! ET C'EST TOUT !!!*/
private:
std::string nom;
int annee;
};
#endif // AUTOMATE_HPP
Tu remarqueras que je renvoye le nom sous la forme d'une std::string const &; c'est à dire sous la forme d'une référence constante
sous la forme d'une référence (&)pour éviter de créer une copie de la chaine de caractères si ce n'est pas nécessaire (parce que la copie, ca prend du temps et qu'elle utilise de la mémoire)
sous une forme constante parce que je ne veux surtout pas que celui qui la récupère puisse modifier le nom
De même, tu remarqueras le mot clé const qui "traine" après la parenthèse fermante: Il permet de déclarer la fonction comme étant une fonction membre constante, c'est à dire qu'elle s'engage à ne pas modifier l'instance en cours d'utilisation (exactement comme la fonction affiche() ).
Grâce à cet accesseur, nous pouvons désormais accéder au nom de notre automate en lecture seule : on peut l'obtenir et l'utiliser, mais on ne peut pas le modifier. Nous pouvons, par exemple, l'utiliser sous une forme proche de
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
A propos de ce cours d'openclassrooms et de l'école, je vois que oui c'est du C++ mais c'est pas récent...
Je suis le cours sur zeste de savoir. Je comprends maintenant que je dois vraiment me mettre a jour, Merci
C'est tellement évident de la manière dont je l'ai fait que son prof en tirera les conséquences qui s'imposent, au niveau des notes du devoir, et, qui sait, avec un peu de chances, il se dira qu'il est plus que temps de s'intéresser au C++ moderne
- Edité par koala01 18 janvier 2020 à 14:35:15
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
Si il réfléchit bien à la question, il devrait même changer de langage, c++ étant de nos jours ce qu'il y a de pire pour enseigner à des débutants.
Autre fois c'était le truc généraliste conseillé par Microsoft a la place de C, d'où une certaine popularité. Maintenant c'est un truc compliqué de specialistes, pour un usage de niche (où il rend bien service, mais niche quand meme)
- Edité par michelbillaud 18 janvier 2020 à 15:05:42
Si il réfléchit bien à la question, il devrait même changer de langage, c++ étant de nos jours ce qu'il y a de pire pour enseigner à des débutants.
Autre fois c'était le truc généraliste conseillé par Microsoft a la place de C, d'où une certaine popularité. Maintenant c'est un truc compliqué de specialistes, pour un usage de niche (où il rend bien service, mais niche quand meme)
- Edité par michelbillaud il y a moins de 30s
Il a choisi un langage pour son exercice...aidons le juste a mieux comprendre ce qu'il a ecris.
Et moi personnellement j'aime le C++, c'est meme sa complexite qui m'attire plus....
Pas d'aide concernant le code par MP, le forum est là pour ça :)
En recherche d'emploi.
git is great because Linus did it, mercurial is better because he didn't.
Pas d'aide concernant le code par MP, le forum est là pour ça :)
Pas d'aide concernant le code par MP, le forum est là pour ça :)