Partage
  • Partager sur Facebook
  • Partager sur Twitter

Instance de classe A dans classe B

Une méthode de classe et la lecture des attributs de cette classe

Anonyme
16 juin 2017 à 14:40:22

Bonjour. Retraité j'aborde depuis peu le C++ calibre 11 (?) dans l'idée de ne pas laisser dépérir mémoire et réflexion. Il y a des tortures plus douloureuses. Depuis trois jours je tourne en boucle, pas code blocks.. Je fais appel auxconfirmés pour m'éclairer sur les résultats que j'obtiens. Merci par avance.

Base : une classe A avec un attribut privé, initialisé par paramètre. Une classe B avec seul attribut une instance de A initialisée à une valeur (int) quelconque mais différente de zéro. (question de lisibilité).

Dans A une méthode "afficher" pour accéder à la valeur de l'attribut. Cette méthode appelée du "Main" confirme l’initialisation de l'attribut.

Dans B une méthode appelle par l'intermédiaire de l'instance de A à la même méthode afficher de A. Le résultat obtenu est la valeur d'initialisation de l'instance de A dans B. Pourquoi ?.

L'utilisation d'un accesseur Get dans les mêmes conditions donne le même résultat.

Par contre lorsque l'attribut de A est initialisé par valeur directement dans le constructeur de A tous les résultats sont corrects. Pourquoi ?. Est-ce à dire qu’une méthode d’une classe n’a pas toujours accès aux attributs de sa propre classe ou est-ce dû à la maladresse d’un débutant ?

Codes :

#include <iostream>

#include "ClassA.h"

#include "ClassB.h"

using namespace std;

int main()

{

 Avant temp(33);

temp.afficher();

Arriere tante;

tante.afficher();

tante.getm_mot();

 return 0;

}


//ClassA.h//ClassB.h

#ifndef CLASSA_H_INCLUDED#ifndef CLASSB_H_INCLUDED

#define CLASSA_H_INCLUDED#define CLASSB_H_INCLUDED

#include "ClassA.h"

class Avantclass Arriere

{{

public:public:

Avant(int nox);Arriere();

~Avant();~Arriere();

void afficher();void afficher();

void getm_mot();void getm_mot();

private:private:

int m_age;Avant m_mot;

};};

#endif // CLASSA_H_INCLUDED#endif // CLASSB_H_INCLUDED


//ClassA.cpp// ClasseB.cpp

#include <iostream>#include <iostream>

#include "ClassA.h"#include "ClassB.h"

#include <string>

using namespace std;using namespace std;

Avant::Avant(int nox): m_age(nox)Arriere::Arriere(): m_mot(0)

{{

}}

Avant::~Avant()Arriere::~Arriere()

{{

}}

void Avant::afficher()void Arriere::afficher()

{{

}m_mot.afficher();

}

int Avant::getm_age() constvoid Arriere:: getm_mot()

{{

return m_age;m_mot.getm_age();

}}

                                                         

-
Edité par Anonyme 16 juin 2017 à 14:50:15

  • Partager sur Facebook
  • Partager sur Twitter
16 juin 2017 à 14:49:00

Lu'!

Merci d'utiliser le bouton de l'éditeur prévu à cet effet pour présenter du code (voir règles d'utilisation du forum). Là c'est complètement illisible.

Sinon quelques notes :

  • le mot méthode n'existe pas dans la norme C++, on parle de fonction membre,
  • le mot attribut n'existe pas non plus, on parle de variable membre,
  • le mot clé const n'est pas une option,
  • utiliser using namespace std est une mauvaise pratique (raison + que faire ?),
  • des getters void c'est au bas mot étrange,
  • si le destructeur ne fait rien pas la peine de le déclarer.

En attendant que tu reformates ton post, j'ai un peu la flemme de chercher la raison de ton problème vu que ce n'est pas lisible.

-
Edité par Ksass`Peuk 16 juin 2017 à 15:11:22

  • Partager sur Facebook
  • Partager sur Twitter

Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

16 juin 2017 à 15:02:29

Attention @Ksass tu as oublié le lien pour namespace std ^^ ton copier coller de post ne marche plus ?
  • Partager sur Facebook
  • Partager sur Twitter
16 juin 2017 à 15:11:32

Non, il y est :-° .
  • Partager sur Facebook
  • Partager sur Twitter

Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

16 juin 2017 à 16:19:31

Salut,

C'est le bordel dans ton source.
Première chose, quand on parle d'une classe nommée avec un certain nom, on aime bien retrouver ce dernier dans le source, ce qui n'est pas ton cas.
Tu nous parles d'une classe "A", et d'une classe "B", hors ton source montre une classe "Avant"
Ou sont passées les fameuses classes "A" et "B" ?
Ensuite, la fameuse classe "A" est supposée n'avoir qu'une variable membre (de type connu mais nom inconnu), et qu'une fonction membre (affiche), hors ton source en montre plus.
Tout laisse à penser que le source ne correspond pas au problème que tu nous expose.

Sinon, ce dont tu nous parles fais penser soit à une aggrégation, soit à une composition.
Dans tous les cas, pour l'initialisation des variables ,que ce soit des variables de type primitif, ou des objets (instances de classe), tout se passe dans le constructeur et nulle part ailleur.

  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
16 juin 2017 à 17:47:51

Bonjour. Retraité j'aborde depuis peu le C++ calibre 11 (?) dans l'idée de ne pas laisser dépérir mémoire et réflexion. Il y a des tortures plus douloureuses. Depuis trois jours je tourne en boucle, pas code blocks.. Je fais appel auxconfirmés pour m'éclairer sur les résultats que j'obtiens. Merci par avance.

Base : une classe Avant avec un attribut privé, initialisé par paramètre. Une classe arriere avec seul attribut une instance de Avant initialisée à une valeur (int) quelconque mais différente de zéro. (question de lisibilité).

Dans Avant une méthode "afficher" pour accéder à la valeur de l'attribut. Cette méthode appelée du "Main" confirme l’initialisation de l'attribut.

Dans B une méthode appelle par l'intermédiaire de l'instance de Avant  la même méthode afficher de Avant. Le résultat obtenu est la valeur d'initialisation de l'instance de A dans B. Pourquoi ?.

L'utilisation d'un accesseur Get dans les mêmes conditions donne le même résultat.

Par contre lorsque l'attribut de Avant est initialisé par valeur directement dans le constructeur de Avant tous les résultats sont corrects. Pourquoi ?. Est-ce à dire qu’une méthode d’une classe n’a pas toujours accès aux attributs de sa propre classe ou est-ce dû à la maladresse d’un débutant ?

Toutes mes excuses pour la mauvaise présentation sans couleurs mais comment faire ? .Si j’utilise un vocabulaire inadéquat c’est parce que je l’ai trouvé dans les cours. Enfin je ne crois pas que mon vocabulaire ait une influence sur le résultat ? Quant à le présence du destructeur j’en prends note pour la suite.Merci

Mes salutations à celui dont la réponse inadéquate dénote son incapacité à faire une transposition analogique.

// Main

#include <iostream>

#include "ClassA.h"

#include "ClassB.h"

using namespace std;

int main()

{

Avanttemp(55);

temp.afficher();

temp.getm_age();

Arriere tante;

tante.afficher();

tante.getm_mot();

return 0;

}

//Class.h

#ifndef CLASSA_H_INCLUDED

#define CLASSA_H_INCLUDED

class Avant

{

public:

Avant(int nox);

~Avant();

void afficher();

int getm_age() const;

private:

int m_age;

};

#endif // CLASSA_H_INCLUDED

/ClassA.cpp

#include <iostream>

#include "ClassA.h"

using namespace std;

Avant::Avant(int nox):m_age(nox)

{

}

Avant::~Avant()

{

}

void Avant::afficher()

{

}

int Avant::getm_age() const

{

return m_age;

}

//ClassB.h

#ifndef CLASSB_H_INCLUDED

#define CLASSB_H_INCLUDED

#include "ClassA.h"

class Arriere

{

public:

Arriere();

~Arriere();

void afficher();

void getm_mot();

private:

Avant m_mot;

};

#endif // CLASSB_H_INCLUDED

// ClasseB.cpp

#include <iostream>

#include "ClassB.h"

#include <string>

using namespace std;

Arriere::Arriere(): m_mot(88)

{

}

Arriere::~Arriere()

{

}

void Arriere::afficher()

{

m_mot.afficher();

}

void Arriere:: getm_mot()

{

m_mot.getm_age();

{

  • Partager sur Facebook
  • Partager sur Twitter
16 juin 2017 à 18:02:47

>Toutes mes excuses pour la mauvaise présentation sans couleurs mais comment faire ?

Utilisez le bouton [</>] !!!!

  • Partager sur Facebook
  • Partager sur Twitter
Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
16 juin 2017 à 18:08:51

Salut Parmenide,

Tu as le bouton "</>" juste au dessus du champ de réponse sur lequel tu dois cliquer, ça t'ouvre une fenêtre puis tu dois choisir comme langage "C++".

Ça va t'insérer une balise code.

Pas besoin d'autre manip' ni de couleurs, elles seront mises par la balise code.

Tu verras, c'est plus lisible et ça aide pour avoir plus de réponses.

Par contre, je ne vois pas où on te dit que tu utilises un vocabulaire inadéquat ? Les termes dans ton premier post me semblent corrects.

Si on ne te répond pas, c'est pas forcément par "incapacité à faire une transposition analogique", c'est surtout qu'il y a facilement + de 100 messages par jour postés sur ce forum et que les gens n'ont pas le temps de trop s'attarder.

Deedolith a exprimé le reste.

  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
16 juin 2017 à 21:10:04

Bon ! nouveau départ laissons tomber cette mauvaise entrée en matière.
Merci à bacelar et à Scorbutics pour leurs éclaircissements....... mais je crois que la balise est perdue en mer .
Mon code est complet, compilé sans problème sur code blocks et tourne parfaitement . Il n'a d'autre but que de m'assurer la possibilité,
exprimée d'une façon générale, que dans le cas de deux classes A et B, une instance de A, attribut de la classe B, peut accéder à tous les éléments,attributs compris, de la classe A . Ben oui je débute alors je vérifie.
Pour ce faire, j'ai construit le code  sur deux classes "Avant" et "Arriere". Les résultats obtenus ne sont pas conformes à ce que
j'espérais, d'où ma demande: maladresse ou impossibilité.
Dans la mouture initiale transmise en second, celle non emmêlée par votre éditeur, j'ai simplement supprimé les " cout " destinés à vérifier
les résultats. J'en ai simplement rajouté deux ici.
//Main
#include <iostream>
#include "ClassA.h"
#include "ClassB.h"
using namespace std;

int main()
{
Avant temp(55);
temp.afficher();
temp.getm_age();
Arriere tante;
tante.afficher();
tante.getm_mot();
return 0;
}

//Class.h

#ifndef CLASSA_H_INCLUDED
#define CLASSA_H_INCLUDED

class Avant
{
public :
Avant(int nox);
~Avant();
void afficher();
int getm_age() const;

private:
int m_age;
};
#endif // CLASSA_H_INCLUDED

//ClassA.cpp

#include<iostream>
#include "ClassA.h"
using namespace std

Avant::Avant(int nox): m_age(nox) // nox ou int selon cas
{
}
Avant::~Avant()
{
}
void Avant::afficher()
{
cout<<"m_age  ="<<m_age<<endl;/verification
}
int Avant::getm_age() const
{
return m_age;
}

// ClassB.h

#ifndef CLASSB_H_INCLUDED
#define CLASSB_H_INCLUDED
#include "ClassA.h"

class Arriere
{
public:
Arriere();
~Arriere();

void afficher();
void getm_mot();

private:
Avant m_mot; // instance de class Avant
};
endif//CLASSB_H_INCLUDED

// classB.cpp

#include <iostream>
#include "ClassB.h"
#include "string"
using namespace std;

Arriere::Arriere() : m_mot(88) // valeur au pif
{
}
Arriere::~Arriere()
{
}
void Arriere::afficher()
{
m_mot.afficher()// appel par l'instance
}
void Arriere::getm_mot()
{
m_mot.getm_age();
cout<<"m_age   ="<<m_mot.getm_age()<< endl;
}


J'espère ne pas avoir fait d'erreur de recopie

Salutations

  • Partager sur Facebook
  • Partager sur Twitter
16 juin 2017 à 21:32:47

Parmenide a écrit:

Dans B une méthode appelle par l'intermédiaire de l'instance de Avant la même méthode afficher de Avant. Le résultat obtenu est la valeur d'initialisation de l'instance de A dans B. Pourquoi ?.

L'utilisation d'un accesseur Get dans les mêmes conditions donne le même résultat.

Désolé, je ne comprends pas la question.
Ce qu'il y a dans le code : quand demande à Arrière d'afficher(), il utilise l'afficher() de son membre Avant qui consiste à ne rien faire.
Le résultat obtenu est ... (le résultat obtenu par quoi, où, quand; quel rapport avec la fonction afficher()?)

Parmenide a écrit:

Par contre lorsque l'attribut de Avant est initialisé par valeur directement dans le constructeur de Avant tous les résultats sont corrects. Pourquoi ?.

Euh, quels résultats?
Si on regarde la fonction getm_mot(), comme ça a déjà été dit, cette fonction lit l'age du membre Avant, et n'en fait rien. Elle est void et ne retourne rien. Cela aurait plus de sens en écrivant plutôt

int Arriere::getm_mot()const {
     return m_mot.getm_age();
} 

Parmenide a écrit:

Est-ce à dire qu’une méthode d’une classe n’a pas toujours accès aux attributs de sa propre classe ou est-ce dû à la maladresse d’un débutant ?

Là je peux répondre oui car une classe à toujours accès à ses attributs.

Cordialement,
Dalfab

  • Partager sur Facebook
  • Partager sur Twitter

En recherche d'emploi.

17 juin 2017 à 4:46:05

Quelques petites choses.

using namespace std est une solution de facilité qui a été introduite en 1998, juste après la normalisation de C++. Le but était de permettre au code écrit avant 1998 de pouvoir être compilé par un compilateur "à la norme" sans avoir trop de modifications à faire. Depuis, les programmeurs ont largement eu le temps de reprendre ce code ancien pour ne plus utiliser cette solution de facilité. Du code écrit après 1998 ne devrait en aucun cas utiliser cette directive dans la portée globale et surtout pas dans un header (là, cette saloperie devient virale). Nous sommes en 2017 et tu débutes, donc tu ne peux pas avoir le plus petit début de commencement d'une raison valable pour utiliser cette vacherie, et comme tu es retraité, tu as suffisamment d'expérience de la vie, pour savoir qu'il est facile de prendre une mauvaise habitude, mais que s'en défaire est un vrai calvaire, donc exit using namespace std tout de suite! 

Après, je fais parties des tenants ultra orthodoxe de la POO, c'est à dire, telle qu'elle a été définie à la fin des année 60 par ses inventeurs. Un objet (au sens POO du terme) doit impérativement être pensé en terme de services à rendre (ou de responsabilité(s) à tenir, si tu préfères, c'est équivalent). La seule chose qui importe dans la définition d'un objet, c'est la réponse à la question: quel(s) service(s) mon objet doit il rendre ? Quelle(s) responsabilité(s) va t'il avoir?

Le maître mot là dedans, c'est cohérence. Depuis sa création et jusqu'à sa destruction, mon objet doit impérativement rester cohérent, quoiqu'il arrive, mon objet doit rendre le(s) service(s) que j'attends de lui, peut importe comment il se débrouille pour le(s) rendre, ceci n'est pas mon problème, mais le sien. C'est un peu comme ton boulanger, faire en sorte que son pain soit "bon" c'est son problème, pas le tien, si ton boulanger ne te fournit pas la qualité de pain qui te conviens, tu iras acheter ton pain dans une autre boulangerie. En POO c'est pareil, si un objet n'est pas satisfaisant, on doit pouvoir le remplacer avec un minimum de modifications sur le reste du programme.

Un petit détail (le diable se cache dans les détails), lorsque je parle de service à rendre je met le pluriel entre parenthèses. Ceci n'est pas un effet de style, un bon objet ne devrait avoir qu'une seule responsabilité. La raison, tu la connais forcément, c'est une base immuable de la pensée humaine: "Ne savoir faire qu'une chose, mais la faire bien", "Diviser pour régner" ou le sarcastique "Pourquoi faire simple quand on peut faire compliqué ?" en sont les illustrations les plus populaires. En programmation on parle de principe de responsabilité unique (Single Responsability Principle en anglais ). Le S de SRP est la première lettre d'un autre sigle: SOLID qui résume la base d'une bonne conception objet.

Quand on a tout ça en tête, la POO devient beaucoup plus facile et intuitive, quelque soit le langage de programmation que l'on utilise, car le langage de programmation n'est jamais qu'un formalisme pour exprimer un concept. Le plus important, c'est le concept, pas le formalisme dans lequel on l'exprime ;)

-
Edité par int21h 17 juin 2017 à 4:55:41

  • Partager sur Facebook
  • Partager sur Twitter
Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
Anonyme
17 juin 2017 à 9:51:39

 Merci INT21 pour cette longue profession de foi. Je supprime "using namespace std" ce qui ne change rien,  je  transmets la nouvelle mouture rectifiée, et ma réponse à Dalfab.

Merci Dalfab de m’avoir consacré quelques instants. Je ne suis pas programmeur, je n’ambitionne même pas le bonnet d’âne des programmeurs et je ne peux te répondre de façon péremptoire. Si tu ne comprends rien à la question c’est à l’évidence qu’elle est mal posée. Tu devrais avoir au moins un semblant de réponse en ce qui concerne la méthode afficher en consultant la mouture transmise par moi selon le mode opératoire du site en utilisant l’échelle de la fenêtre et en faisant défiler les diverses interventions. Les autres moutures dont la première ont été transmises dans ma méconnaissance du mode opératoire.

Si j’ai occulté les instructions « cout » c’est parce que j’ai jugé les censeurs éventuels du programme assez avisés pour y remédier d’eux même. Je me suis planté autant pour moi.

En ce qui concerne l’accesseur, il n’accède à aucun attribut de la classe Arriere et son type void se justifie dans cette classe, au contraire de son type int dans la classe Avant où il accède à l’attribut de la classe Avant. La valeur de cet attribut, renvoyée, donne lieu à instruction d’affichage dans la classe Arriere.

Comme tout programme qui se respecte celui-ci a pour résultat la modeste ambition d’afficher la valeur de « m_age », je dis bien la valeur, sousaccès différents.

Pour ta gouverne je te précise que ce programme compile sans problème et affiche correctement les résultats dans la console.

En ce qui concerne les résultats affichés :

lorsque l’attribut m_age de la classe Avant est initialisé par « nox » à la valeur « 55 »par exemple, alors que celui de la classe Arriere est initialisé par valeur à « 88 » par exemple, on obtient :

m_age=55 seule valeur exacte

m_age=88valeur d’initialisation de l’attribut de la classe Arriere 

m_age par retour get88

lorsque l’attribut m_age de la classe Avant est initialisé directement à une valeur, « 99 » par exemple, celle d’initialisation de l’attribut de la classe Arriere sans modification, on obtient :

m_age=99

m_age=99toutes valeurs exactes

m_age=99

Ces résultats, qui devraient t’ouvrir une piste dans la résolution du pourquoi,  me conduisent à soumettre ce simple programme à plus au fait que moi. Il s’agit soit d’une maladresse de programmation soit de la naissance d’un doute pour ce que tu tiens pour acquis dans ton message. Le vrai peut n’être pas vraisemblable.

J’ajoute, au cas où, que si le destructeur n’est pas de mise au cas présent, je le laisse car il peut ne pas être sans utilité. En espérant t’avoir apporté les éclaircissements nécessaires.

Cordialement

// Main

#include <iostream>
#include "ClassA.h"
#include "ClassB.h"



int main()
{

    Avant  temp(55);
    temp.afficher();
    temp.getm_age();
    Arriere tante;

    tante.afficher();
    tante.getm_mot();



    return 0;
}
//ClassA.h

#ifndef CLASSA_H_INCLUDED
#define CLASSA_H_INCLUDED

class Avant
{
public:
Avant(int nox);
~Avant();

void afficher();
int getm_age() const;

private:
  int m_age;

};


#endif // CLASSA_H_INCLUDED
//ClassA.cpp

#include <iostream>
#include "ClassA.h"



Avant::Avant(int nox):m_age(nox)
{

}
Avant::~Avant()
{

}

void Avant::afficher()
{
    std::cout<<"m_age   "<<m_age<<std::endl;
}

int Avant::getm_age() const
{

    return m_age;
}

//ClassB.h

#ifndef CLASSB_H_INCLUDED
#define CLASSB_H_INCLUDED
#include "ClassA.h"

class Arriere
{

public:
    Arriere();
    ~Arriere();

void afficher();
void getm_mot();

private:

    Avant m_mot;


};


#endif // CLASSB_H_INCLUDED


// ClasseB.cpp

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



Arriere::Arriere(): m_mot(88)
{

}
Arriere::~Arriere()
{

}
void Arriere::afficher()
{
  m_mot.afficher();// Appel par instance de la classe arriere
}

void Arriere:: getm_mot()
{
    m_mot.getm_age();
    std::cout<< "m_age  ="<<m_mot.getm_age()<<std::endl;
}
  • Partager sur Facebook
  • Partager sur Twitter
17 juin 2017 à 11:58:57

Désolé, je ne comprends toujours pas

Je pense par contre être capable de lire le code (j'enseigne le C++ depuis  25 ans).
L'instance temp du type Avant a son m_age qui vaut 55, cf construction ligne 12 qui utilise constructeur ligne 52.
L'instance tante du type Arriere a son membre m_mot du type Avant qui a son m_age qui vaut 88, cf construction ligne 15 qui utilise constructeur ligne 107 qui transmet le 88 au constructeur du m_mot ligne 52.

  • Partager sur Facebook
  • Partager sur Twitter

En recherche d'emploi.

17 juin 2017 à 12:37:22

Par essence, un accesseur doit retourner quelque chose, un accesseur donne accès à quelque chose, donc s'il ne retourne rien c'est qu'il y a tromperie sur la marchandise ;)

Un autre point, à mesure que tu vas progresser, tu vas te rendre compte à quel point le nommage est important. En fait, on écrit le code une fois et on est souvent amené à le relire, parfois des mois ou des années après l'avoir écrit. Là, que se passe t'il si le nommage n'a pas été effectué avec le plus grand soin? On ne comprend plus rien à son propre code! Pour te donner un exemple, je bosse sur un programme depuis peut être 15 ans, et que je ne finirai probablement jamais, parce qu'il manquera toujours une fonctionnalité, qu'il y aura toujours un truc qui ne va pas... Le programme en question "pèse" à ce jour un petit million de lignes, je navigue sans soucis au milieu de cet océan de code pour une seule raison: J'ai toujours pris grand soin de tout nommer avec précision, si bien que même si je lis du code que j'ai écrit il y a quinze ans, il reste aussi lisible que si je venais de l'écrire. 

Sur le nommage des fichiers par exemple, si mon fichier contient une classe Avant, il se nommera avant.h et l'implémentation sera dans un fichier avant.cpp.

Ensuite, au niveau du nommage des objets du programme eux mêmes, je vais faire très attention aux noms que je choisis de sorte que leur noms devront toujours exprimer clairement le rôle que j'entends leur faire tenir, c'est à dire les services/responsabilités que j'entends leur assigner, de sorte que si j'ai besoin de revenir dessus, les noms que j'aurai choisi me parleront même si je reviens dessus des années après.

Là tes classes Avant et Arriere ne parlent pas, pas plus que tes fonctions getm_mot, nous on ne sait pas ce que tu veux faire, et toi tu l'auras oublié dans un mois, alors rend nous service et rends toi service aussi au passage, choisis les noms de tes objets (variables, classes, fonctions...) avec beaucoup de soin ;) 

On dit souvent qu'il faut mettre des commentaires, c'est une erreur, car quand on modifie le programme, l'expérience montre qu'on oublie souvent de modifier le commentaire, qui du coup devient faux et peut nous induire en erreur. Il est largement préférable de composer son code de telle sorte qu'il n'y ait pas besoin de commentaire.

-
Edité par int21h 17 juin 2017 à 13:10:40

  • Partager sur Facebook
  • Partager sur Twitter
Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
Anonyme
17 juin 2017 à 16:15:26

Rebonjour Dalfab

N'inversons pas les rôles, si de nous deux il y en a un qui a besoin de comprendre c'est moi..
Je suis parfaitement les deux premières lignes de ta réponse. Par contre je n'accroche pas sur la suite en particulier sur la transmission par le constructeur ligne 107 de la valeur d'initialisation de m_mot au constructeur de m_age ligne 52.
Il me semble si c'était le cas, qu'un mode différent d'initialisation  de l'attribut m_age dans le constructeur ligne 52,à savoir le mode d'origine que tu mentionnes et celui d'une initialisation sous la forme m_age(55) n'aurait pas d'incidence sur les résultats affichés. Ils seraient

semblables dans les deux cas....ce qui n'est pas.
Il suffit pour le constater de faire l'essai.

Je reste sur ma faim, pas grave avec la chaleur.

cordialement

  • Partager sur Facebook
  • Partager sur Twitter
17 juin 2017 à 19:54:58

Il y a un concept que tu as loupé, et comme tu utilises un vocabulaire non habituel, je n'arrive pas à entrer dans ton raisonnement.
Tu dis que je mentionne "mode d'origine", or je n'ai jamais parlé ni de mode ni d'origine.

Il y a des instances d'objets. Ces instances sont caractérisées par un nom et un type. On peut dire que l'instance est une boîte qui contient des 'choses'. Le type est là pour décrire les caractéristiques des 'choses' dans l'instance (par exemple Avant est un type qui contient un int nommé m_age), chacune des instances créées aura un contenu propre (par exemple pour l'instance temp le m_age vaut 55).
Essayons de dessiner nos deux instances : temp de type Avant et tante de type Arriere. A l'intérieur de tante, il y une instance qui est du type Avant; ce m_mot qui est dans tante n'a aucune donnée commune avec le temp, ils sont seulement du même type.

      +-----------+
temp: | m_age: 55 |
      +-----------+

       +------------------------+  temp et tante.m_mot ont des contenus différents
       |         +-----------+  |  ils ont le même type donc ils savent faire la même chose
tante: |  m_mot: | m_age: 88 |  |         
       |         +-----------+  |  temp.getm_age() retourne 55
       +------------------------+  tante.m_mot.getm_age() retourne 88

Il est cependant possible de définir des données dites de classe. Ces données seront alors communes à toutes les instances créées, et en effet dans ce cas, il suffit qu'une des instances modifie la donnée pour que toutes les autres voient celle-ci changer. Je pense que tu avais plutôt en tête ce concept, qui ne doit pas être utilisé sauf dans des cas bien précis.

  • Partager sur Facebook
  • Partager sur Twitter

En recherche d'emploi.

Anonyme
18 juin 2017 à 10:40:59

Rebonjour Dalfab

Merci de m'avoir consacré du temps. Je sais la difficulté de langage et c'est ce qui m'a fait hésiter au début à utiliser le site. La première partie de ta réponse ne me pose pas de problème. C'est en fait la seconde partie qui me semble pertinente même si je n'en saisi pas encore la pleine signification. Je me ferai une raison sur le fait que je fais du concept sans le savoir.(lol)
Je vais considérer que j'ai abordé sans le vouloir un domaine au delà de mon niveau actuel. J'ai au moins la satisfaction d'avoir encore un raisonnement qui se tient.

Sincères remerciements.
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
19 juin 2017 à 14:31:15

Rebonjour.

Me voilà de retour après avoir interrogé le programme. Quand ses réponses ne me conviennent pas je peux au moins me défouler sur lui.

J’ai noté dans l’ordre toutes ses réponses. Elles vous parleront sans doute mieux qu’à moi. Je termine par une question. Une réponse précise et concise serait la bien - venue.

A l’origine de ce petit programme ; la portée d’un instance de classe. Par définition elle a accès à toutes les méthodes de la classe, et comme extérieure à la classe, elle a accès aux attributs d’une classe par l’intermédiaire d’une méthode de la classes . D’une façon lapidaire elle peut avoir accès à tous les éléments de la classe.

Je me suis posé la question que, comme un Pandore je n’aurais pas dû me poser : qu’en est-il lorsque une instance de classe est elle-même attribut d’une autre classe.

Après avoir levé les réticences du compilateur j’en suis arrivé à la situation actuelle que je ne m’explique pas.

Quelqu’un aura-t-il la curiosité de s’y intéresser ?

Merci

Réponses de l’ordinateur :

-Je suis dans le constructeur de la classe Avant ;

-Premier appel de getm_age dans mainm_age = 55 ; // normal

-Je suis à nouveau dans le constructeur de la classe Avant suite à la demande de création de l’objet tante (Arriere tante) ; // curieux, induit par un include ?

-Je suis dans le constructeur de la classe Arriere ;// initialisation de m_mot

-Je vérifie la valeur de m_age en appelant m_mot.afficher m_age = 88 valeur d’initialisation de m_mot .

Au vrai j’affiche bien la valeur de m_mot car celle de m_age est toujours la même ; // première surprise !

-Second appel de getm_age dans main :m_age = 55 ; // la preuve

-Appel de m_mot.getm_age . J’affiche la valeur de m_mot en retour88 ; // confirmation

-Troisième appel de getm_age dans Mainvaleur de retour55 ; // la preuve

-Je suis dans le destructeur de la classe arriere ;// mes condoléances

-Avant-dernier appel de getm_age dans mainvaleur de retour88 ;// surprise ?

-Je suis dans le destructeur de la classe Avant ;//regrets éternels

-Dernier appel de getm_age dans main :valeur de retour 55 // toujours initiale

-Je suis dans le destructeur de la classe Avant//Fin

Ma conclusion : la mienne pas celle de l’ordinateur :

L’instance de la classe Avant comme attribut de la classe Arriere implique il me semble l’inclusion de « classAvant.h » dans « class Arriere.h ». A défaut elle n’est pas reconnue. Cette inclusion génère semble-t-il un second appel de la classe Avant et par suite « l’anomalie » dans les valeurs.

Questions : Existe-t-il une autre option que l’include pour que la classe Arriere reconnaisse l’instance de la classe Avant dans ses attributs ?

  • Partager sur Facebook
  • Partager sur Twitter
19 juin 2017 à 23:24:30

Salut,

Parmenide a écrit:

Rebonjour Dalfab

N'inversons pas les rôles, si de nous deux il y en a un qui a besoin de comprendre c'est moi..

Ah, si tu n'avais pas besoin d'aide, tu aurais peut être raison...

Mais, si tu veux une aide rapide et efficace (ce que beaucoup de gens attendent de la part de l'aide qu'ils demandent, sommes toutes), il faut aussi que ceux qui voudront bien essayer de t'aider puissent comprendre ce que tu cherches à faire, ce que tu fais, et ce qui coince entre les deux.

Un adage dit "aide toi et le ciel t'aidra". sur les forums techniques l'adage principal est "aide nous à t'aider"

Et le plus marrant dans tout cela, c'est qu'en nous aidant à t'aider (entre autres, en faisant en sorte que le code que tu nous présente nous en dise suffisamment sur tes intentions pour que nous puissions voir si ce qui est fait y correspond), il y a de fortes chances pour que tu t'aides toi-même et que la solution finisse par te sauter au yeux, tout simplement ;)

  • Partager sur Facebook
  • Partager sur Twitter
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
Anonyme
20 juin 2017 à 10:31:42

Bonjour Koala01

Je ne suis pas familier avec le jargon C++ aussi il te faudra peut-être faire un effort de transposition. Merci.

Je donne dans l’ordre une réponse à tes interrogations..

Ce que je cherche à faire ? : c’est comprendre pourquoi une « association de classes » construite à partir d’une instance de classe attribut d’une autre classe, association réalisée avec pointeur « * » ou noncomme dans mon exemple, ne donne pas toujours accès aux attributs de sa classe en contradiction apparente avec la définition qui veut qu’un objet (une instance) peut accéder aux données membres de sa classe par l’intermédiaire d’une méthode membre de sa classe.

Ce que je fais : c’est un petit programme construit je l’espère pour vérifier le bien-fondé de mon interrogation

Ce qui coince : c’est la confirmation de mon interrogation sur la portée d’une instance de classe membre d’une autre classe,. C’est paradoxal mais pour une fois le bon résultat n’est pas celui souhaité.

Comme je ne suis pas suffisamment pointu en la matière je souhaiterais une explication qui me rassure sur l’origine de l’incohérence apparente des résultats, en fait savoir s’il s’agit d’une question de forme ou de fond. Par nature je ne peux avancer qu’en ayant confiance en mes acquis.

J’ajoute que lorsque le membre donnée de la classe pointée n’est pas initialisé par copie (paramètre nox) mais par valeur « m_age(int quelconque) » tous les résultats affichés correspondent à la valeur d’initialisation de « m_age ».

En ce qui concerne la présence des fonctions membres « afficher » leur présence n’est pas utile mais au départ ce sont elles que j’ai utilisé pour vérification. A la vue des résultats obtenus j’ai doublé ces fonctions par un accesseur.

Mon avant dernier message donne une image des résultats plus précise que celle d’origine dans la mesure où cette image permet d’attribuer les résultats à chaque attribut et d’évincer un transfert éventuel ou confusion de valeurs entre eux.

Pour l’instant je pédale dans la semoule.

Cordialement

  • Partager sur Facebook
  • Partager sur Twitter
20 juin 2017 à 10:34:13

Exécute ton code pas à pas avec un debugger et trace les variables dont tu veux comprendre le comportement.

  • Partager sur Facebook
  • Partager sur Twitter

Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

20 juin 2017 à 12:11:21

>-Je suis à nouveau dans le constructeur de la classe Avant ... curieux, induit par un include ?

Non. C'est dû à la composition de votre classe "Arriere".

Au moment de la construction d'un objet "Arriere", avant l'appel du constructeur de la classe, chaque champ de la classe qui n'est pas d'un type primitif (int, float, double, ...) est initialisé, soit en appelant le constructeur dans paramètre du type du champ, soit, si le champ est mentionné dans la liste d'initialisation, le constructeur correspondant (majoritairement, le constructeur de copie)

Arriere::Arriere(): m_mot(88)

La liste d'initialisation permet aussi d'initialiser les champs de type primitif.

Donc, avant même que le constructeur de "Arriere" n'ai commencé, "this.m_mot.m_age" est déjà égal à 88.

>classe Arriere implique il me semble l’inclusion de « classAvant.h »

Vous confondez tout. Remettez les choses à plat.

>-Second appel de getm_age dans main :m_age = 55 ; // la preuve

La preuve de quoi ???

temp et tante.m_age ne partagent que leur type, rien d'autres.

>-Appel de m_mot.getm_age . J’affiche la valeur de m_mot en retour88 ; // confirmation

Conformation de quoi ????!!!!

Soyez plus explicite, SVP !!!

  • Partager sur Facebook
  • Partager sur Twitter
Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
20 juin 2017 à 16:23:41

Parmenide a écrit:

Bonjour Koala01

Je ne suis pas familier avec le jargon C++ aussi il te faudra peut-être faire un effort de transposition. Merci.

Je n'ai aucun effort de transposition à faire ici, vu, qu'en l'occurrence, mon intervention ne contient aucun terme technique à part "code" :D

Je donne dans l’ordre une réponse à tes interrogations..

Ce que je cherche à faire ? : c’est comprendre pourquoi une « association de classes » construite à partir d’une instance de classe attribut d’une autre classe, association réalisée avec pointeur « * » ou noncomme dans mon exemple, ne donne pas toujours accès aux attributs de sa classe en contradiction apparente avec la définition qui veut qu’un objet (une instance) peut accéder aux données membres de sa classe par l’intermédiaire d’une méthode membre de sa classe.

Je ne suis pas sur de comprendre ce que tu penses être correct, mais je peux te confirmer une chose : si tu déclares dans une classe (nommons la "utilisateur, pour savoir de laquelle on parle) une donnée membre dont le type est lui-même une classe (nommons la "outil" par facilité) proposant une fonction publique permettant d'accéder à une de ses données membre, n'importe quelle fonction de ta "première" classe ("utilisateur", selon mon exemple) peut accéder à la fonction de sa donnée membre ("outil", selon mon exemple, et donc, d'une certaine manière, à la donnée membre de la donnée membre (la donnée membre de "outil")

Ce qui se passe, c'est que ce que tu pourras faire avec cette valeur obtenue dépendra des différentes décisions que tu auras prises lors de l'écriture de ta classe "outils", bien sur, mais aussi de ta classe "utilisateur"

Ce que je fais : c’est un petit programme construit je l’espère pour vérifier le bien-fondé de mon interrogation

Ce qui coince : c’est la confirmation de mon interrogation sur la portée d’une instance de classe membre d’une autre classe,. C’est paradoxal mais pour une fois le bon résultat n’est pas celui souhaité.

C'est que le programme ne décrit pas correctement tes intentions. Car si tes intentions étaient correctement décrites dans le programme, tu obtiendrais forcément le résultat auquel tu t'attend ;)

Si bien que cela nous ramène à ce que je disais plus haut: si tu veux pouvoir avoir une confirmation (à condition que ton intuition soit juste, bien sur), il faut déjà commencer par nommer les éléments (types de données, fonctions, données) qui t'intéressent correctement, de manière à ce que leur nom décrive l'usage auquel tu les destines. Tu peux me croire, ca simplifie la vie de tous :

La notre bien sur, car les noms que tu auras choisi nous permettront de "vérifier" si les intentions que tu décrit sous forme de phrase correspondent exactement à la manière dont tu les as décrites dans le code

Mais le plus important, c'est que cela te facilitera la vie à toi aussi, car, toi aussi, tu seras en mesure de faire (au moins en partie) cette vérification

Comme je ne suis pas suffisamment pointu en la matière je souhaiterais une explication qui me rassure sur l’origine de l’incohérence apparente des résultats, en fait savoir s’il s’agit d’une question de forme ou de fond. Par nature je ne peux avancer qu’en ayant confiance en mes acquis.

L'explication "simple", je viens de te la donner: les intentions que tu décrit dans ton code ne correspondent pas aux intentions que tu décrit sous forme de phrases

Cela va -- forcément -- introduire la question suivante : pourquoi en est-il ainsi?

Et la réponse à cette nouvelle question sera que c'est trop difficile à dire "en l'état", car nous sommes dans l'incapacité d'"extrapoler" ce à quoi tu pensais au moment où tu écrivais ton code sur base de celui-ci

Ce qui, bien sur, nous ramène au fond du problème : il faut écrire ton code de manière à ce que n'importe qui puisse "se mettre à ta place" et comprendre ce à quoi tu pensais lorsque tu as écrit ton code.

Allez, comme je suis de bonne humeur, voici un code qui devrait confirmer (ou infirmer) ce que tu cherches à démontrer.  Du moins, si j'ai bien compris tes explications ;)

// serait dans outils.h
#ifndef OUTIL_H_INCLUDED
#define OUTIL_H_INCLUDED
class Outil{
public:
    Outil();
	Outil(int val);
	// il est "de bon ton" d'indiquer au compilateur
	// les fonctions membres qui ne modifie EN AUCUN CAS
	// la classe
	void affiche() const;
	int laValeurDoutil() const;
private:
    int laValeur;
};
#endif //OUTIL_H_INCLUDED
//serait dans utilisateur.h
#ifndef UTILISATEUR_H_INCLUDED
#define UTILISATEUR_H_INCLUDED
// décommente la ligne suivante si tu sépare le tout
//include <outil.h>
class Utilisateur{
public:
    Utilisateur();
	Utilisateur(int age);
	Utilisateur(int age, int valeurDoutil);
	void affiche() const;
	int lAgeDuCapitaine() const;
private:
   int lAge;
   Outil lOutil;
};
#endif //UTILISATEUR_H_INCLUDED
// serait dans Outil.cpp
// décommente la ligne suivante si tu sépare le tout
// #include <outil.h>
#include <iostream> 
Outil::Outil():laValeur{35}{
	std::cout<<"Outil cree sans donner de valeur a laValeur\n"
	         <<"je lui ai donne la valeur "<<laValeur<<" moi-meme\n";
}
Outil::Outil(int val ):laValeur{val}{
	std::cout<<"Outil cree avec val = "<<val<<"\n"
	         <<"j'ai donne la valeur "<<laValeur<<"a laValeur\n";
}
void Outil::affiche() const{
	std::cout<<"Dans outil.affiche(), laValeur = "<<laValeur<<"\n";
}
int Outil::laValeurDoutil() const{
	std::cout<<"laValeurDoutil() renvoie "<<laValeur<<"\n";
	return laValeur;
}
// serait dans utilisateur.cpp
// décommente la ligne suivante si tu sépare le tout
// #include <utilisateur.h>
#include <iostream>
Utilisateur::Utilisateur():lAge{45}{
	std::cout<<"Utilisateur cree sans donner de valeur a lAge\n"
	         <<"je lui ai donne la valeur "<<lAge<<" moi-meme\n";
}
Utilisateur::Utilisateur(int age):lAge{age}{
	std::cout<<"Utilisateur cree avec la valeur age ="<<age<<"\n"
	         <<"j'ai donne la valeur "<<lAge<<" a l'Age\n";
}
Utilisateur::Utilisateur(int age, int valeurDoutil):lAge{age},lOutil{valeurDoutil}{
	std::cout<<"Utilisateur cree avec la valeur age ="<<age<<" et \n"
	         << " valeurDoutil="<<valeurDoutil<<"\n"
	         <<"j'ai donne la valeur "<<lAge<<" a l'Age et transmis"
			 <<" valeurDoutil a l'outil\n";
}
void Utilisateur::affiche() const{
	std::cout<<"Utilisateur::affiche() : lAge = "<<lAge<<"\n";
	lOutil.affiche();
}
int Utilisateur::lAgeDuCapitaine() const{
	std::cout<<"lAgeDuCapitaine() renvoie "<<lAge<<"\n";
	return lAge;
}
// serait dans main.cpp
// décommente les deux lignes qui suivent si tu sépare le tout
//#include <outil.h>
//#include <utilisateur.h>
#include <iostream>
int main(){
	 Outil premier;
	 premier.affiche();
	 std::cout<<premier.laValeurDoutil()<<"\n";
	 Outil second{18};
	 second.affiche();
	 std::cout<<second.laValeurDoutil()<<"\n";
	Utilisateur cap1;
	cap1.affiche();
	std::cout<<cap1.lAgeDuCapitaine()<<"\n";
	Utilisateur cap2(89);
	cap2.affiche();
	std::cout<<cap2.lAgeDuCapitaine()<<"\n";
	Utilisateur cap3(54,18);
	cap3.affiche();
	std::cout<<cap3.lAgeDuCapitaine()<<"\n";
}

Tu remarqueras que les roles sont maintenant inversés : c'est maintenant à toi de "entrer dans ma tete" pour savoir si le code que j'ai écrit correspond aux explications que tu m'as données.

Mais, comme j'ai pris la peine de choisir des noms qui, à défaut d'être parfaitement utiles, indiquent clairement l'usage qui sera fait des différents éléments, ce genre de code te permet de te faire une idée de ce que j'ai compris de ton explication.

Et, partant de là, tu pourras donc me dire si je n'ai pas bien compris quelque chose (et donc me permettre de corriger le code en conséquence) ;)

-
Edité par koala01 20 juin 2017 à 17:11:13

  • Partager sur Facebook
  • Partager sur Twitter
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
Anonyme
21 juin 2017 à 9:48:21

Bonjour Bacelar

Une réponse rapide je dois répondre à des obligations fruitières.
Rappel des raisons de ma demande d'aide. Contrairement à la déclaration de foi du programmeur qui se doit d'élaborer un programme

conduisant à un résultat prédéfini, le programme que je soumets à la sagacité de qui veut, a été élaboré sans but prédéfini si ce n'est

par curiosité, pour voir le résultat. Je n'ai pas cherché à obtenir ce résultat, j'ai seulement été surpris par lui. Je ne peux donc répondre

à la question " que cherches-tu à faire " ?
Un électricien qui installe dans une pièce interrupteur, liaison filaire et ampoule le fait pour un résultat prédéterminé à savoir allumer

cette ampoule.
Un visiteur ultérieur, sans connaissance particulière en matière d'électricité, entre dans la pièce et s'interroge sur l'utilité de cet

interrupteur. Il l'enclenche et n'obtient rien.
S'il interroge l'électricien ce dernier lui répond " il sert à allumer le lampadaire". Cette réponse n'instruit en rien le visiteur qui constate par

expérience que ce n'est pas le cas.
Mis à part les commentaires, les mentions  dans mon dernier message sont celles restituées par mes balises destinées à retranscrire le

déroulement du programme. Elles sont ce qu'elles sont et le moment où elles apparaissent n'est pas de mon fait. Elles me permettent par

contre de vérifier que, contrairement à ce que peut donner à penser la lecture éditée des différentes valeur de l'attribut " m_age" durant

le déroulement du programme, sa valeur d'initialisation n'est jamais  modifiée durant le programme puisqu'on la retrouve en fin. Pour une

raison que je ne m'explique pas, (je suis le visiteur ignorant), durant le déroulement du programme c'est la valeur d'initialisation de

"m_mot" qui est éditée au lieu et place de celle demandée à savoir celle de "m_age".
Pour accroitre encore ma perplexité lorsque l'attribut "m_age" est initialisé par valeur et non par surcharge les valeurs éditées durant le

déroulement du programme, aux mêmes points, sont uniquement celle de la valeur d'initialisation de "m_age".Exit à l'édition celle de

"m_mot"
J'ai sans doute mal assimilé les quelques notions que j'ai acquises pour ne pas avoir compris que sous deux termes différents, type et

valeur, on trouve la même chose.
Ma conclusion est simple: il y a une raison de forme ou de fond pour que les résultats édités soient ce qu'ils sont et ce que je recherche

à faire c'est trouver une explication à cette raison.
Il faut que j y aille.

Cordialement
  • Partager sur Facebook
  • Partager sur Twitter
21 juin 2017 à 14:08:34

Si on doit filer la métaphore de l’électricien, je pense qu'on n'est plus dans :

L’électricien installe un télérupteur mais que l'utilisateur pense que ça marche comme un va-et-vient.

Vous êtes l'utilisateur, qui cherche à calquer sa compréhension fausse à ce qu'il voit.

Vous devez remettre ne question votre compréhension.

Vous nous surinez avec des modifications de "m_age" qui ne sont pas effectuées mais vous n'avez toujours pas compris qu'il y a 2 zones mémoires complètement différentes, une pour le champ "m_age" de la variable "temp" et une pour le champ "m_age" de la variable "tante.m_mot". Changez la valeur de l'une n'a aucun effet sur l'autre.

  • Partager sur Facebook
  • Partager sur Twitter
Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
Anonyme
21 juin 2017 à 15:43:29

Bonjour Koala01

Je tiens d’abord à te remercier pour ta démarche qui amorce une intention de compréhension de la mienne. Je ne me suis pas encore penché sur ton programme mais sur ta longue phrase qui débute par « Je ne suis pas sûr de comprendre … ». J’ai eu du mal à la traduire,enfin à traduire ce que tu voulais me faire comprendre. Sans rire. Même toi tu as eu des difficultés pour la conclure de façon supposée claire pour moi. Merci de tes efforts.

Néanmoins, sur la base de ton affirmation j’ai écrit un petit petit programme que j’espère cette fois bien documenté, car il n’est pas à mon seul usage. Il est fondé sur la distinction de classe de ton exemple : une classe Outil et une classe Utilisateur .

Je ne crois pas te surprendre en te disant que le résultat est identique à celui obtenu dans mon exemple de classe Avant et Arrière.

Autrement dit, sans savoir pourquoi ni comment, je ne peux à défaut d’explication , m’aligner sans réserve sur ta certitude d’accès général aux données membres par une méthode membre.

Ou cet accès est la règle intangible et il y a une malfaçon dans ce petit programme ou cette règle souffre d’exception.

Pour ma part je ne suis pas en mesure de trancher.

Merci

Cordialement

#include <iostream>
#include "ClasseOutil.h"
#include "ClassUtilisateur.h"


/* ce projet(?) comporte une classe Utilisateur et une classe Outil.
La réalité veut que l'Utilsateur utilise l'Outil plutôt que l'Outil
utilise l'Utilisateur*/
/*Par ordre dans le Main, le premier appel de l'accesseur pour obtenir le nbre de pinces
usées,membre donnée de Outil, donne 99 qui est la valeur d'initialisation de la donnée
membre "m_pince" type Outil dans le SourceUtilisateur.cpp. alors que le second appel pour
obtenir à nouveau le nbre de pinces usées, membre donnée de Outil, donne la valeur correcte
55 qui est la valeur d'initialisation du nombre de pinces usées dans la classe Outil */

int main()
{
Utilisateur NbrePincesCrocodilesUsees; //initialisation du nbre d'usées dans ClassUtilisateur

//appel de l'accesseur dans la classe Utilisateur

NbrePincesCrocodilesUsees.appelDeGetm_nombrePincesCrocodilesUsees(); //résultat  99

 // initialisation par surcharge de l'objet du nombre de pinces croco usées

Outil pincesUsees(55);

// appel de l'accesseur dans la classe Outil

pincesUsees.getm_nombrePincesCrocodilesUsees();  // résultat correct 55

std::cout<<" Valeur en retour de getm_nombrePincesCrocodilesUsees   ="<<std::endl;
std::cout<<pincesUsees.getm_nombrePincesCrocodilesUsees()<<std::endl;

    return 0;
}


#ifndef CLASSUTILISATEUR_H_INCLUDED
#define CLASSUTILISATEUR_H_INCLUDED

#include "ClasseOutil.h"

class Utilisateur
{
public:

    Utilisateur();    //  constructeur


    void appelDeGetm_nombrePincesCrocodilesUsees(); // accès à l'attribut de la classe outil






private:

     Outil m_pince;            // déclaration de l'attribut type Outil.


};



#endif // CLASSUTILISATEUR_H_INCLUDED


#include <iostream>
#include "ClassUtilisateur.h"

// constructeur. Pas de destructeur pour alléger cette mouture
 // non pas mouture de café mais de classe. Destructeur d'office

Utilisateur::Utilisateur(): m_pince(99)
{

}
// le titre parle de lui même, le résultat moins.

void Utilisateur::appelDeGetm_nombrePincesCrocodilesUsees()
{
  m_pince.getm_nombrePincesCrocodilesUsees();
  std::cout<<" NbrePincesCrocodilesUsees   "<<m_pince.getm_nombrePincesCrocodilesUsees()<<std::endl;
  std::cout<<std::endl;
}

#ifndef CLASSEOUTIL_H_INCLUDED
#define CLASSEOUTIL_H_INCLUDED




class Outil
{
public:
    Outil(int usees);                        // constructeur de la classa Outil



int getm_nombrePincesCrocodilesUsees();       // accés à la seule donnée membre
                                             // pour ne pas surcharger l'écriture.


private:


    int m_nombrePincesCrocodilesUsees;        //c'est le nombre de pinces crocodiles usees
};


#endif // CLASSEOUTIL_H_INCLUDED


#include <iostream>
#include "ClasseOutil.h"


Outil::Outil(int usees):m_nombrePincesCrocodilesUsees(usees) // constructeur de la classe Outil. Pas de constructeur,

                                                              //destruction effectuée d'office
{

}
int Outil:: getm_nombrePincesCrocodilesUsees()
{

    return m_nombrePincesCrocodilesUsees;             // retourne dans la classe Utilisateur
                                                      // le nombre de pinces crocodiles usées
}

  • Partager sur Facebook
  • Partager sur Twitter
21 juin 2017 à 15:56:18

Vous n'avez toujours pas compris à quoi servent les classes et les objets.

Votre code est exactement le même qu'avant, seule les noms changent.

Et comme avant, "NbrePincesCrocodilesUsees.m_pince.m_nombrePincesCrocodilesUsees" n'est pas égale à "pincesUsees.m_nombrePincesCrocodilesUsees" car c'est 2 zones mémoires complètement différentes.

-
Edité par bacelar 21 juin 2017 à 15:57:17

  • Partager sur Facebook
  • Partager sur Twitter
Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
Anonyme
21 juin 2017 à 16:06:45

bonjour bacelar

Bonjour

Bon et alors ?  Si vous êtes sur la bonne voie vous pouvez  aussi m'expliquer pourquoi , lorsque on souhaite accéder à m_age on obtient  la valeur de m.mot ?

Ce serait de nature à affiner ma compréhension et à vous permettre de gonfler la votre.

Je note en passant que vous n'êtes pas tenu de  répondre à mes questions.

Merci.

Bonjour

Je pense qu’il est nécessaire de faire une mise au point à l’attention des intervenants.

Par principe je postule la sincérité de vos interventions. Je vous invite pourtant à respecter le mode opératoire suivant :

polarisez votre attention sur le programme élémentaire que j’ai écrit en première réponse à Koala. Ilne peut être plus simple. Si les termes utilisés pour désigner les classes et les deux variables ne vous conviennent pas rien ne vous empêche de les réécrire en chinois, sous forme de lettres de l’alphabet, d’idéogrammes ou de runes si le cœur vous en dit et si compilateur l’admet . Dès l’instant où vous en respectez l’esprit , vous le lancez.

Soit les deux résultats sont égaux et correspondent à la valeur d’initialisation de la variable accédée soit ils ne le sont pas. Dans les deux cas vous devriez être à même d’en tirer les bonnes conclusions et de m’en faire part.

Inutile de faire des commentaires en dehors de ce mode opératoire. Ils n’ont pas d’autre résultat que de dévaloriser le sérieux et la raison d’être de ce site.

Pour terminer j’ajouterai que si j’avais à recruter l’un d’entre vous , ce qui n’est pas le cas, le seul sur lequel porterait mon choix est Koala pour la simple raison qu’il a été jusqu’à maintenant le seul à tenter une explication.

Il y a un problème qui n’est pas de mon fait que vous le vouliez ou non. Il est sans doute plus difficile à cerner qu’une affaire de point-virgule raison pour laquelle il semble vous échapper.

En dehors de ce mode opératoire passez votre chemin vos interventions sont inutiles. Je n’ai pas moi non plus de temps à perdre.

Merci.

-
Edité par Anonyme 23 juin 2017 à 8:28:53

  • Partager sur Facebook
  • Partager sur Twitter
21 juin 2017 à 16:20:51

> lorsque on souhaite accéder à m_age on obtient  la valeur de m.mot ?

Pouvez-vous nous indiquer à qu'elle ligne de votre code "vous souhaitez accéder à m_age" ?

(Avec la ligne SVP, car vous avez posté pas mal de version de votre code).

  • Partager sur Facebook
  • Partager sur Twitter
Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
21 juin 2017 à 16:55:06

Ca ne serait pas possible de revenir à une question élémentaire, genre

<< - je pensais que ceci était possible (code MINIMAL fourni, montrant une seule chose) / que ça ferait ceci

- et apparemment non / ca fait autre chose , pourquoi ? >>

Parce que là on se perd dans des tas de considérations.

Si j'ai bien compris, il s'agit d'une classe où une donnée membre est une instance d'une autre classe. Le code de départ serait

class A  {
private:
   int m_x;        // pas besoin de plus
};

class B {
   A m_a;          // une instance de A
};

et ensuite ?

On s'interesse aux mécanismes du langage semble-t-il, donc en rester à des noms volontairement dépourvus de connotations, ne mettre aucun accesseur qui ne soit pas absolument indispensable pour formuler la question, etc.

Il fait trop chaud pour réfléchir, et la vie est trop courte pour perdre son temps à des conneries.

-
Edité par michelbillaud 21 juin 2017 à 17:02:46

  • Partager sur Facebook
  • Partager sur Twitter