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 :

Declarer un pointeur vers une classe sans new ?


Sujet :

C++

  1. #1
    Membre à l'essai
    Inscrit en
    Avril 2006
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 24
    Points : 20
    Points
    20
    Par défaut Declarer un pointeur vers une classe sans new ?
    Pour ceux qui ont suivi la discussion precedente, vous devez vous dire que je dois etre allergique au new.

    Alors cette fois ma question est:

    Si on declare une classe de la facon suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Class myClass
    {
    int toto;
    int function(int a);
    }
    int MyClass::function(int a)
    {
    return a;
    }
    Si on fait par ailleurs:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    MyClass* myObject;
    int b;
    b = myObject->function(10);
    Ca marche !!! Et on a bien b = 10 !

    Par contre


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    MyClass* myObject;
    int b;
    b = myObject->toto;
    La on se prend un memory access violation.

    Alors pourquoi peut-on acceder aux methodes d'un objet sans l'instancier, en definissant simplement un pointeur sur un type ?

    Tant que la methode ne touche pas aux variables de la classe, en gros ca marche.

    C'est normal docteur ? Comment ca marche tout ca?

    Qu'est ce qu'il y a reelement dans le pointeur myObject avant l'instance d'un new ? Vers quoi pointe-t-il ?

  2. #2
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par zi_omnislasher Voir le message
    Alors pourquoi peut-on acceder aux methodes d'un objet sans l'instancier, en definissant simplement un pointeur sur un type ?

    Tant que la methode ne touche pas aux variables de la classe, en gros ca marche.

    C'est normal docteur ? Comment ca marche tout ca?

    Qu'est ce qu'il y a reelement dans le pointeur myObject avant l'instance d'un new ? Vers quoi pointe-t-il ?
    Parce que tu as de la chance....
    Mais je pense que c'est le compilot qui a remplacé
    int b = toto->fonction(10);
    par int b= 10

  3. #3
    Membre averti Avatar de Kujara
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    262
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 262
    Points : 358
    Points
    358
    Par défaut
    Citation Envoyé par zi_omnislasher Voir le message
    Alors pourquoi peut-on acceder aux methodes d'un objet sans l'instancier, en definissant simplement un pointeur sur un type ?

    Tant que la methode ne touche pas aux variables de la classe, en gros ca marche.

    C'est normal docteur ? Comment ca marche tout ca?
    Bah, vi, c'est normal.

    Reflechit 2 secondes :

    Une fonction membre d'une classe, par rapport a une fonction normale, le seul truc qui change, c'est l'instance de la classe en question.

    Donc si tu touche pas a la classe en question, tu peux lui passer n'importe quoi en param( valeur du pointeur de la classe), vu que la fonction n'y touche pas, ta fonction deviens une fonction normale avec un param inutilisé( this ), donc ça passe.

  4. #4
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    L'appel d'une méthode sur un objet non initialisé a un comportement indéfini. Sur certains compilos ça plante, sur d'autres non (mauvais point d'ailleurs à mon avis).

    En gros lorsque tu compiles une classe, le compilo crée en mémoire une structure contenant les fonctions de cette classe (ou pointeur sur les fonctions). Un appel du type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    myClass->myFunction()
    sera en fait un appel à myFunction de la structure dont je parlais précédemment, avec un paramètre supplémentaire : le this.

    En gros l'adresse des fonctions sera la même pour toutes les instances d'une classe. Donc avant un new, un pointeur contient une adresse invalide. Mais comme tu as déclaré le type de ce pointeur, le compilo sait quelle table de fonction correspond à cette instance.

    Ensuite, lorsque tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MyClass* myClass = new MyClass;
    La mémoire est allouée pour l'instance spéficique myClass, cette mémoire contient en fait chaque donnée membre déclarée dans la classe MyClass.

    COmme je le disais, quand tu appelles une fonction de MyClass, l'instance particulière pour laquelle tu as appelé cette fonction est passé en paramètre. Dans l'exemple que tu fournis, cette instance est invalide, i.e. aucune mémoire n'a été allouée, les données membres n'ont pas été initialisées. Si ta fonction n'accède pas à ces données (autrement dit n'utilise pas le this), ça ne plante pas.

    En résumé :

    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
     
    class A {
     
    public:
     
    A(int toto=0) : valeur(toto) {}
    void myMethode();
     
    private:
     
    int toto;
    };
     
     
    //Plus loin dans le code
    A* a;
    //Ici le compilo sait que a est du type A*, donc il connaît l'adresse de la
    //fonction à appeller si on fait a->quelquechose. a pointe vers une zonne de
    //mémoire invalide.
     
    a = new A;
    //Ici la mémoire nécessaire est allouée (autrement dit le nombre d'octets pour
    //stocker toto), et toto est initialisé avec la bonne valeur. a pointe
    //maintenant vers une zone de mémoire valide.

  5. #5
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Points : 833
    Points
    833
    Par défaut
    Dis toi bien que la plupart du temps on utilise l'allocation dynamique par pointeurs lorsqu'on veut gérer soit même la durée de vie d'un objet

    Dans bien des cas il est plus sage de sans passer tout simplement et de passer les objets en paramètre par référence plutôt que par pointeur.

    référence ou pointeurs

    FAQ :
    Utilisez les références aussi souvent que possible, et les pointeurs quand vous le devez.
    Linux > *

  6. #6
    Membre éclairé
    Homme Profil pro
    Consultant ERP
    Inscrit en
    Février 2004
    Messages
    644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant ERP

    Informations forums :
    Inscription : Février 2004
    Messages : 644
    Points : 785
    Points
    785
    Par défaut
    Un gros conseil, lit un livre C++, s'il te plait.
    Nul ne peut mieux connaitre la connaissance qu'elle-même.

  7. #7
    Membre à l'essai
    Inscrit en
    Avril 2006
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 24
    Points : 20
    Points
    20
    Par défaut
    Parce que tu as de la chance....
    Mais je pense que c'est le compilot qui a remplacé
    int b = toto->fonction(10);
    par int b= 10
    En fait si on fait

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Class MyClass
    {
    int function(int a, int b);
    }
     
    int MyClass::function(int a, int b)
    {
    int result = a+b;
    return result;
    }
    La aussi ca marche parfaitement.

    Pour Kujara j'arrive pas a copier coller le passage la, mais dans tous les cas explique moi ce que fait le new vis a vis des methodes?

    Pire quand tu fais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MyClass* myObject = NULL;
    On peut acceder aux methodes de la meme facon !!! Alors qu'on a un pointeur NULL !

    Donc quand on fait

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MyClass* myObject;
    On fait une operation qui a un sens tres precis que j'aimerais comprendre.

    Est-ce qu'un objet en C++ c'est pas simplement un pointeur vers une structure qui contient les variables d'une part, et d'autre part qui gere les methode dans une structure independante, cree au moment de la declaration ?

    Le new dans ce cas ne s'occuperai que de la structure qui gere les variables.

    Le new n'aurait aucun lien avec les methodes.

    Ca change beaucoup de chose, ca explique beaucoup de bugs.

  8. #8
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    Citation Envoyé par zi_omnislasher Voir le message
    En fait si on fait

    Est-ce qu'un objet en C++ c'est pas simplement un pointeur vers une structure qui contient les variables d'une part, et d'autre part qui gere les methode dans une structure independante, cree au moment de la declaration ?
    Lis mon post

  9. #9
    Membre à l'essai
    Inscrit en
    Avril 2006
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 24
    Points : 20
    Points
    20
    Par défaut
    Ah ben voila Bolhrak a completement repondu a ma question.

    C'est bien ce que je pensais.

    Tres interessant. Merci.

    J'aimerais avoir le temps de lire un livre sur le C++.

    Merci a tous.

    PS : J'etais justement en train d'ecrire le mien quand tu as poste.

  10. #10
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    essai cela

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Class MyClass
    {
    int function(int a, int b);
    int c;
    }
     
    int MyClass::function(int a, int b)
    {
    int result = a+b+c;
    return result;
    }

  11. #11
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    Citation Envoyé par zi_omnislasher Voir le message
    Ah ben voila Bolhrak a completement repondu a ma question.

    C'est bien ce que je pensais.

    Tres interessant. Merci.

    J'aimerais avoir le temps de lire un livre sur le C++.

    Merci a tous.
    Note bien que le fait que ça ne plante pas est spécifique à une implémentation. Ce que j'ai décrit est très grossier, chaque compilo implémente ça à sa manière avec ses tweaks etc. Bref ce n'est pas une chose sur laquelle se baser pour développer. Un pointeur non initialisé n'a pas à être utilisé. Si tu considères pourvoir appeler ta méthode sans avoir besoin d'instance de la classe, revois ta conception (méthode statique ou fonction libre).

  12. #12
    Membre à l'essai
    Inscrit en
    Avril 2006
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 24
    Points : 20
    Points
    20
    Par défaut
    essai cela

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Class MyClass
    {
    int function(int a, int b);
    int c;
    }
     
    int MyClass::function(int a, int b)
    {
    int result = a+b+c;
    return result;
    }
    Bien sur que ca plante, mais c'est un cas different dont je parlais. C'est la facon d'instancier qui m'interessait au final.
    Cet exemple revient a faire directement myObject->c (ce que je disais dans le 1er post). Je pense que l'erreur est la meme.

  13. #13
    Membre à l'essai
    Inscrit en
    Avril 2006
    Messages
    24
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 24
    Points : 20
    Points
    20
    Par défaut
    Note bien que le fait que ça ne plante pas est spécifique à une implémentation. Ce que j'ai décrit est très grossier, chaque compilo implémente ça à sa manière avec ses tweaks etc. Bref ce n'est pas une chose sur laquelle se baser pour développer. Un pointeur non initialisé n'a pas à être utilisé. Si tu considères pourvoir appeler ta méthode sans avoir besoin d'instance de la classe, revois ta conception (méthode statique ou fonction libre).
    Justement c'etait pour expliquer aux gens avec lesquels je bosse pourquoi leur programme il marche, mais qu'il pue le bug a plein nez.

  14. #14
    Membre éclairé
    Homme Profil pro
    Consultant ERP
    Inscrit en
    Février 2004
    Messages
    644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant ERP

    Informations forums :
    Inscription : Février 2004
    Messages : 644
    Points : 785
    Points
    785
    Par défaut
    Citation Envoyé par zi_omnislasher Voir le message
    Justement c'etait pour expliquer aux gens avec lesquels je bosse pourquoi leur programme il marche, mais qu'il pue le bug a plein nez.
    Si leur programme est comme le code que tu as écrit en exemple, c'est normal qu'il bug.

    Voici un exemple robuste de code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    boost::shared_ptr< MyClass > myClass( new MyClass() );
    myClass->function( x, y );
    Inutile de désallouer la mémoire explicitement, c'est le boost::shared_ptr qui s'en occupe.
    Nul ne peut mieux connaitre la connaissance qu'elle-même.

  15. #15
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 366
    Points : 444
    Points
    444
    Par défaut
    Citation Envoyé par swirtel Voir le message
    Voici un exemple robuste de code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    boost::shared_ptr< MyClass > myClass( new MyClass() );
    myClass->function( x, y );
    Inutile de désallouer la mémoire explicitement, c'est le boost::shared_ptr qui s'en occupe.
    Autant utiliser les auto_ptr standard dans ce cas là. Les shared_ptr ne devraient être utilisés que pour ce pour quoi ils ont été conçus : la gestion des ressources partagées.

  16. #16
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Le jeu des fonctions n'accédant pas à this n'est pas forcément standard, mais certaines implémentations le définissent.
    Notamment l'implémentation de Microsoft (Visual C++), qui met ces règles à profit dans sa bibliothèque MFC :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    UNTYPE * CUneClasse::GetSafePtr()
    {
    	return (this==NULL ? NULL : m_ptr);
    }
    Mais évidemment, rien ne garantit que ça marche ailleurs, donc un tel code est à déconseiller...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. pointeur vers une autre classe
    Par Invité dans le forum Débuter
    Réponses: 9
    Dernier message: 19/11/2010, 13h10
  2. Utilité d'un pointeur vers une fonction ?
    Par Nasky dans le forum C
    Réponses: 10
    Dernier message: 20/03/2010, 19h54
  3. [Frames] un lien vers une page de Frames vers une page sans
    Par jamesleouf dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 23/09/2005, 18h25
  4. Réponses: 14
    Dernier message: 14/03/2005, 09h16
  5. [MFC] Problème pointeur sur une classe
    Par mick74 dans le forum MFC
    Réponses: 7
    Dernier message: 14/04/2004, 14h17

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