C++: atteindre une instance dans 1 autre fichiers source
Répondre à la discussion
Affichage des résultats 1 à 22 sur 22

C++: atteindre une instance dans 1 autre fichiers source



  1. #1
    Bounoume

    C++: atteindre une instance dans 1 autre fichiers source


    ------

    Avec QTCreator, je dispose d'un "MainWindow.cpp".
    J'y ai rajouté un objet Thread01 (instance d'une classe dérivée de QThread...), avec diverses méthodes...

    1)J'ai ajouté au projet un fichier "kernel.cpp", avec son en-tête "kernel.h".... qui déclare 1 classe "Kernel"
    Dans MainWindow.cpp j'ai placé #include "kernel.h"...... donc (?).........
    Depuis MainWindow.cpp, pas de problème pour déclarer 1 objet de classe Kernel, (déclaré ailleurs donc) et pour y accéder....

    2)J'ai ajouté au projet un fichier "nodes.cpp", avec son en-tête "nodes.h".... qui déclarent 1 classe "nodes"
    et des classes dérivées
    dans" kernel.h" il y a le #include "nodes.h".........
    idem: Depuis Kernel.CPP, pas de problème pour déclarer 1 objet de classe Nodes, et pour y accéder....

    Par contre depuis nodes.cpp, refus d'intégrer dans une fonction (de l'objet nodes) aucune fonction d'une instance d'objet Thread1 ou Kernel., déclaré dans un autre fichier cpp.
    Message: nodes.cpp:40: erreur : 'the_kernel' was not declared in this scope & 'le_nodes' was not declared in this scope

    J'ai l'impression que les instances d'un objet ne sont visibles que dans le 'scope' où on les a déclarées.....
    J'ai tenté de charcuter les "#include", en vain, seulement production de plein d'erreurs supplémentaires.....
    Je m' y perds et ne trouve rien sur ces règles sur les sources, dans les documentations accédées...
    Alors
    Comment accéder à une fonction d'un objet en dehors du fichier .cpp où il a été déclaré?
    merci d'avance

    -----
    rien ne sert de penser, il faut réfléchir avant.... (Pierre Dac...)

  2. #2
    Chanur

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par Bounoume Voir le message
    J'ai l'impression que les instances d'un objet ne sont visibles que dans le 'scope' où on les a déclarées.....
    Oui, bien sûr. Et pas seulement les instances d'une classe : c'est vrai pour n'importe quelle variable (les variables de types natifs (int, double, ...) ou les pointeurs aussi bien que les instances de classes).
    Citation Envoyé par Bounoume Voir le message
    Comment accéder à une fonction d'un objet en dehors du fichier .cpp où il a été déclaré?
    merci d'avance
    En général, on passe l'objet en argument à la méthode ou la fonction qui en a besoin.
    Attention : le passage d'argument consiste à recopier la variable, ce qui peut gaspiller du temps et/ou des ressources. Si on veut éviter ça, on utilise en général le passage par référence au lieu du passage par valeur.
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  3. #3
    Bounoume

    Re : C++: atteindre une instance dans 1 autre fichiers source

    OK, va pour la référence, un pointeur, pour agir sur l'objet et pas une copie, pour utiliser LA fonction qui va modifier ses propriétés (ou appeler une autre fonction dans SA portée.
    je pense à un raise signal -> slot d' 1 objet graphique .......

    Seulement ce qui coÏnce, c'est comment écrire l'égalité pour les instances:
    déclarer ça, dans la portée où j'en ai besoin, je sais (dans une fonction quelconque d'1 objet de type nodes:
    Kernel * ptr_vers_the_kernel;
    nodes * ptr_vers_le_nodes;

    -> accepté par le compilateur

    mais comment faire avaler, toujours dans nodes.cpp:
    ptr_vers_the_kernel=the_kernel ;
    ptr_vers_le_nodes=le_nodes;


    là, le compilateur refuse..... avec l'habituel message: the_kernel' was not declared in this scope
    rien ne sert de penser, il faut réfléchir avant.... (Pierre Dac...)

  4. #4
    Chanur

    Re : C++: atteindre une instance dans 1 autre fichiers source

    C'est impossible ç comprendre si tu ne donne pas ton code.
    Pour moi, il suffit de passer the_kernel à la fonction ou à la méthode qui en a besoin, mais manifestement ce n'est pas ça.

    Quand aux signaux Qt, rien à voir : ça sert à passer des informations d'un thread à un autre.
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  5. A voir en vidéo sur Futura
  6. #5
    Bounoume

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Voici 1 exemple ( la fonction est appelée depuis une fonction quelconque, mais qui est dans le nodes.cpp qui a besoin d'accéder à l'objet Kernel::the_kernelsitué dans kernel.cpp)

    dans nodes.cpp
    bool nodes::setProperties()
    {
    Kernel * copie_Kernel;
    copie_Kernel->copieur(this,the_kernel);
    return 0;
    }
    ;la fonction copie,
    dans kernel.cpp:
    void Kernel::copieur(Kernel * cible,Kernel * source)
    {cible=source; return;};
    Kernel * the_kernel;
    the_kernel= new ... etc.... etc....
    l'erreur:
    /home/ebauche-0/nodes.cpp:168: erreur : 'the_kernel' was not declared in this scope
    copie_Kernel->copieur(this,the_kernel);
    ^
    rien ne sert de penser, il faut réfléchir avant.... (Pierre Dac...)

  7. #6
    Chanur

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Oui, donc c'est ce que je disais : tu as dans ta méthode setProperties une variable non déclarée : the_kernel
    Comment voudrais-tu que le compilateur sache ce qu'elle désigne ? Il ne connais pas la variable. Il ne sais pas de quelle type elle est, ni quelle est son adresse. Et ce n'est certainement pas en se fiant au nom qu'il va essayer de deviner son type : si tu remplaces "the_kernel" par "toto", tu auras exactement la même erreur.

    Il suffit d'ajouter à setProperties un argument Kernel & the_kernel.
    Comme ça, ça se compilera, et ça plantera dès que tu essaieras de lancer setProperties :
    Code:
    bool nodes::setProperties(Kernel & the_kernel)
    {
    Kernel * copie_Kernel;
    copie_Kernel->copieur(this,the_kernel);
    return 0;
    }
    copie_kernel a une valeur non définie, ce qui rend extrêmement improbable que l'appel à copie_Kernel->copieur puisse fonctionner.
    (dans le meilleur des cas (et le plus vraisemblable), ça plante et dans le pire des cas, ça marche en donnant un résultat indéfini)
    Dernière modification par Chanur ; 28/07/2018 à 12h42.
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  8. #7
    Bounoume

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par Chanur Voir le message
    Il suffit d'ajouter à setProperties un argument Kernel & the_kernel.
    Comme ça, ça se compilera, et ça plantera dès que tu essaieras de lancer setProperties :
    copie_kernel a une valeur non définie, ce qui rend extrêmement improbable que l'appel à copie_Kernel->copieur puisse fonctionner.
    (dans le meilleur des cas (et le plus vraisemblable), ça plante et dans le pire des cas, ça marche en donnant un résultat indéfini)
    Effectivement, appeler 1 méthode d'un objet référencé par 1 pointeur non encore défini......
    J'ai contourné le problème avec un troisième objet Kernel, lui réellement créé par 1 'new' : Kernel *zombie ......
    Code:
    bool  nodes::setProperties(Kernel & the_kernel)
    {
    Kernel * copie_Kernel; // reste non défini.....
    Kernel * zombie=new Kernel;
    zombie->copieur(copie_Kernel,the_kernel);  //copie_    devrait pointer sur le vrai the_kernel
    delete zombie;
    return 0;
    };
    Seulement il me faut re-définir ma fonction set_properties(Kernel * ....) dans nodes.h
    Code:
    bool setProperties(Kernel &  the_kernel);
            protected:
            nodes * Caller; // à t.......
    Seulement là ça est refusé, bien que j'aie mis en début de nodes.h
    Code:
    #include <kernel.h>
    le message est
    /home/ebauche-0/nodes.h:67: erreur : 'Kernel' has not been declared bool setProperties(Kernel & the_kernel);
    alors que le mot Kernel (que j'ai souligné dans le code au_dessus) est bien reconnu car coloré en rose dans l'éditeur [si j'enlève le #include "kernel.h" , alors c'est pas coloré comme 1 type]
    ^
    rien ne sert de penser, il faut réfléchir avant.... (Pierre Dac...)

  9. #8
    polo974

    Re : C++: atteindre une instance dans 1 autre fichiers source

    c'est le pb des références circulaires sauf erreur:

    la classe A doit connaître la classe B et vice versa...
    regarde par là par exemple, il y une discussion sur où placer ce qu'il faut (et comme c'est un débat, ce n'es pas tranché ...)

    (ne pas oublier d'initialiser les pointeurs, sinon, ils vont pointer droit dans le mur...)
    Jusqu'ici tout va bien...

  10. #9
    Bounoume

    Re : C++: atteindre une instance dans 1 autre fichiers source

    la discussion sur les inclusions est bien complexe....J'ai l'impression qu' elle concerne la définition de types dépendant les uns des autres.....
    ce qui ne me semble pas cafouiller dans mon truc: pas de problème pour déclarer une nouvelle instance d'un type donné , quel que soit le .cpp où je le déclare.
    peux placer un
    Kernel * kernel_quelconque; où je veux;

    ce que je ne peux faire, c'est le déclarer ICI, le construire ICI, et ensuite accéder à une de ses fonctions LA, dans un autre .cpp .....

    Je viens de voir quelque chose qui doit avoir un rapport avec le problème:
    les fichiers source (.cpp) sont compilés indépendamment en fichiers objet .o ...... puis liés avant exécution......

    cela n'expliquerai-il pas pourquoi y a pas moyen habituellement d'accéder à 1 instance dans 2 fichiers source différents!

    Pourtant il doit exister des directives qui permettent de transmettre l'adresse /l'accès à une donnée d'un fichier source à 1 autre.
    Pour forcer le compilateur partager les accès entre plusieurs sources, comment faire?
    Directive 'extern' ?' 'static' ,'forward' ou autre?
    Je ne trouve aucune nomenclature avec documentation sur les mots réservés en compilation.....
    rien ne sert de penser, il faut réfléchir avant.... (Pierre Dac...)

  11. #10
    Chanur

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Oui, il existe une façon habituelle de transmettre l'adresse d'une donnée : le passage de paramètre (pourquoi ai-je l'impression de me répéter ?)
    Le problème n'est absolument pas la séparation entre deux fichiers .cpp : cette séparation est totalement arbitraire. On peut toujours concaténer deux fichiers .cpp en un seul, on obtiendra exactement le même résultat.

    Ce que tu supposes (à tort) c'est que si une variable est déclarée quelque part, on doit y avoir accès partout. Heureusement que ce n'est pas le cas. Ce serait un joyeux foutoir : n'importe quel programme pourrait accéder à n'importe quelle variable déclarée dans une bibliothèque ....

    Les règles sont simples :
    - une variable locale (automatique ou statique) n'est accessible que dans le bloc (entre "{" et "}" ) où elle est définie, et seulement après sa définition.
    - un attribut (ou une méthode) ne peut être utilisé qu'en connaissant l'instance de la classe concernée (et avec des restriction suivant qu'elle est publique, protégée ou privée), sauf pour les attributs (ou méthodes) statiques qui sont des variables de classes et qui ne dépendent pas de l'instance : il suffit de connaître la classe
    - une variable globale (ou une fonction) statique ne peut être utilisée que dans le source où elle est définie et seulement après sa définition.
    - une variable globale non statique peut être utilisée partout : elle doit être définie une seule fois mais peut être déclarée autant de fois qu'on veut, en la déclarant comme "extern". Pour une fonction, c'est pareil : elle ne peut être définie qu'une fois, mais peut être déclarée autant de fois qu'on veut : c'est la déclaration du prototype (le mot clé "extern" est facultatif pour les fonctions). Si la fonction est utilisée, elle doit être définie, sinon peu importe (comme pour les méthodes).

    Quand aux mots-clés du langage C, on les trouve partout ...

    Quand aux fichiers includes, il est impératif de les protéger contre les inclusions mutiples comme ça :

    node.h:
    Code:
    class Node;
    #ifndef NODE_H
    #define NODE_H
        #include "kernel.h"
        class Node
            {
            ...
            Kernel * kernel;
            void set_Kernel (Kernel * kernel) { this->kernel = kernel; };
            }
    #endif
    kernel.h:
    Code:
    class Kernel;
    #ifndef KERNEL_H
    #define KERNEL_H
        #include "node.h"
        class Kernel
            {
            ...
             Node * node;
            }
    #endif
    main.cpp:
    Code:
    #include "node.h"
    #include "kernel.h"
    int main ()
        {
        Kernel machin;
        Node truc;
        truc.set_kernel (&machin);
        return 0;
        }
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  12. #11
    polo974

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par Bounoume Voir le message
    ...

    cela n'expliquerai-il pas pourquoi y a pas moyen habituellement d'accéder à 1 instance dans 2 fichiers source différents!

    Pourtant il doit exister des directives qui permettent de transmettre l'adresse /l'accès à une donnée d'un fichier source à 1 autre.
    Pour forcer le compilateur partager les accès entre plusieurs sources, comment faire?
    Directive 'extern' ?' 'static' ,'forward' ou autre?
    Je ne trouve aucune nomenclature avec documentation sur les mots réservés en compilation.....
    Il y a la façon propre exposée par Chanur. Elle permet d'avoir plusieurs groupes de classes liées.

    Et il y a la façon bien crade qui consiste à déclarer tes classes de façon globale et ailleurs de les déclarer en extern... Tes variables (classes ou pas) seront visibles de partout, est-ce un bon choix ???

    Maintenant en Qt, tu peux récupérer l'appli (instance unique) dont presque tout dépend (si tu respectes leur façon de coder), tu peux la récupérer avec:
    • qApp global pointer
    • QApplication::instance() static function
    et dans ton appli, tu dois avoir ton arbre de classes...
    Jusqu'ici tout va bien...

  13. #12
    Fustigator

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par polo974 Voir le message
    Il y a la façon propre exposée par Chanur. Elle permet d'avoir plusieurs groupes de classes liées.

    Et il y a la façon bien crade qui consiste à déclarer tes classes de façon globale et ailleurs de les déclarer en extern... Tes variables (classes ou pas) seront visibles de partout, est-ce un bon choix ???
    Pourquoi une solution aussi bâtarde ? Les patterns IoC (DI et SL par exemple) servent (entre autre) à éviter cela et sont très faciles à implémenter.

  14. #13
    Chanur

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par Fustigator Voir le message
    Pourquoi une solution aussi bâtarde ? Les patterns IoC (DI et SL par exemple) servent (entre autre) à éviter cela et sont très faciles à implémenter.
    Parce que je suis une bille en C++. Ma spécialité, c'est le C.

    Je n'ai jamais pensé qu'il y ait un design pattern sur la question, mais maintenant que tu le dis, ça me paraît assez évident.

    Tu peux nous en dire plus ?
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  15. #14
    Fustigator

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par Chanur Voir le message
    Parce que je suis une bille en C++. Ma spécialité, c'est le C.

    Je n'ai jamais pensé qu'il y ait un design pattern sur la question, mais maintenant que tu le dis, ça me paraît assez évident.
    Ma réponse faisait référence à "la façon bien crade" exposée par polo974, pas à la tienne.

    Sinon, pour la mise à disposition d'instance (mais pas que), deux patterns (entre autres) répondent à ce type de problématique :
    - L'injection de dépendance
    - Le Service Locator.

    Ce sont tous les deux des patterns qu'on classe de manière très générique dans les "inversions de contrôle".

    La mise ne place d'un service locator basique est très simple (pour les cas moins simples, il y a des bibliothèques dédiées).

    L'injection de dépendance est plus sophistiquée et on utilise en général des bibliothèques dédiés.

    Le plus simple est de voir les notice wiki sur la question :
    https://en.wikipedia.org/wiki/Dependency_injection
    https://en.wikipedia.org/wiki/Service_locator_pattern

  16. #15
    pm42

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Vu le niveau des questions posées, je ne suis pas sur que les design patterns soient accessibles.
    Sans parler du fait que l'IOC et le Service Locator pour partager une bête variable entre 2 classes C++ relèvent du marteau et la mouche...
    Dernière modification par pm42 ; 31/07/2018 à 15h36.

  17. #16
    Fustigator

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par pm42 Voir le message
    Vu le niveau des questions posées, je ne suis pas sur que les design patterns soient accessibles.
    Sans parler du fait que l'IOC et le Service Locator pour partager une bête variable entre 2 classes C++ relèvent du marteau et la mouche...
    Pas faux.
    Mais un SL, ca peut aussi se faire en quatre lignes et deux méthodes. Ca reste un SL (minimaliste certes).
    Et ça oblige à structurer un peu ce qu'on veut faire.

  18. #17
    pm42

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par Fustigator Voir le message
    Pas faux.
    Mais un SL, ca peut aussi se faire en quatre lignes et deux méthodes. Ca reste un SL (minimaliste certes).
    Et ça oblige à structurer un peu ce qu'on veut faire.
    Dans l'absolu, je serais assez d'accord. Mais après avoir lu ce fil et son prédecesseur sur les signaux/slots en Qt, je pense qu'il faut introduire les nouveaux concepts lentement.

  19. #18
    Bounoume

    Re : C++: atteindre une instance dans 1 autre fichiers source

    bonjour chanur&polo974, et les autres.....
    ben j'avais déjà pris la solution crade.....
    l'objet the_Kernel déclaré hors de toute fonction, au début de mainwindow.cpp (c'est le vrai nom dans le programme en difficile gestation ....): j'ai besoin d'appeler certaines de ses fonctions en début d'exécution....
    l'objet Kernel est construit dans kernel.cpp et kernel.h
    avec sa méthode à moi utile (soit.... Unid=the_kernel.getNew_unid(); ) appelée dans le troisième source, qui est nodes.cpp

    Avec des include qui ont l'air de convenir; pas d'inclusions croisées entre nodes.h et kernel.h: kernel.h inclut nodes.h pour d'autres raisons (le boulot de kernel est de gérer plein de nodes) Evidemment il y a les
    Code:
    #ifndef NODE_H    
    #define NODE_H
    ............
    #endif
    etc.....
    Tiens, chanur, ça, pour toi c'est du pipeau de base, mais ça m'avait dépanné, un peu avant que je lise ta réponse
    http://mcours.net/cours/pdf/info/REF..._LANGAGE_C.pdf page 68

    Ainsi, officiellement, "MON" problème est résolu: merci à vous;

    mais y a des choses en suspens:
    c'est quoi (en 2 mots) votre 'passage de paramètres'?
    Et puis, en pinaillant:
    Code:
    #include "node.h"
    #include "kernel.h"
    int main ()
        {    Kernel machin;
        Node truc;
        truc.set_kernel (&machin);
        return 0;    }
    pour ça, dans l'en-tête nodes.h, tu as déclaré une première fois la classe node avant les directives #ifndef
    puis, après #define.... , comme d'habitude, le prototype complet de la classe
    ( idem avec l'autre classe dans l'autre en-tête).
    Je retiens, au cas où j'aurais à utiliser 2 classes qui contiennent chacune une instance de l'autre.... OK

    mais dans main, truc.set_kernel mettrait-t-il l'adresse de 'machin' dans la propriété pointeur Kernel * kernel du node truc.... ?
    Est-ce ça?
    rien ne sert de penser, il faut réfléchir avant.... (Pierre Dac...)

  20. #19
    Ikhar84
    Animateur Informatique

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par Bounoume Voir le message
    Je retiens, au cas où j'aurais à utiliser 2 classes qui contiennent chacune une instance de l'autre
    Salut,

    Juste histoire de mettre mon grain de sel dans cette galère.

    Avant d'aller plus loin, je pense qu'il faudra se mettre à bien réflechir au design des classes, via UML, par exemple, une bonne conception en amont aurait déjà régle la plupart des problèmes qui se sont posés ici.
    J'ai glissé Chef !

  21. #20
    polo974

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par Fustigator Voir le message
    Pourquoi une solution aussi bâtarde ? Les patterns IoC (DI et SL par exemple) servent (entre autre) à éviter cela et sont très faciles à implémenter.
    ben oui, ce n'est pas pour rien que j'ai dit "bien crade", je ne coderais ça que pour une terrible vengeance (ou en cas d'immense grosse flemme (et une petite vengeance))...

    maintenant, quel est le coût de l'usage de ces design patterns? une ou deux indirections à chaque accès, je suppose...
    Jusqu'ici tout va bien...

  22. #21
    pm42

    Re : C++: atteindre une instance dans 1 autre fichiers source

    Citation Envoyé par polo974 Voir le message
    maintenant, quel est le coût de l'usage de ces design patterns? une ou deux indirections à chaque accès, je suppose...
    Codé normalement, il n'y a pas de coût.

  23. #22
    Bounoume

    Re : C++: atteindre une instance dans 1 autre fichiers source

    le crade: bien reçu.....
    Alors, pour rester au ras de pâquerettes:
    est-ce le fait de mettre un Objet en variable globale ordinaire(même sans aucune directive Extern dans aucune autre source) qui est douteux?

    Si OUI, alors comment on fait quand on utilise un Thread , forcément contrôlé par une instance de QThread?
    Pour le moment il est en variable globale: au moins je suis sûr de sa pérennité.
    Le déclarer static? et/ou alors où déclarer l'instance ? dans quelle fonction?


    ps: pas trop d'inquiétude quand même: mon 'joujou' personnel n'a aucune vocation à mise en production.... ni même, sauf miracle, à passer en d'autres mains plus expertes...
    rien ne sert de penser, il faut réfléchir avant.... (Pierre Dac...)

Discussions similaires

  1. Combien de temps pour atteindre une autre étoile ?
    Par the_gexx dans le forum Physique
    Réponses: 31
    Dernier message: 02/09/2016, 19h59
  2. Probabilité d'atteindre un nœud avant un autre.
    Par julien_4230 dans le forum Mathématiques du supérieur
    Réponses: 3
    Dernier message: 07/04/2014, 08h30
  3. JAVA Utiliser une instance dans une autre classe
    Par invitea7f787d2 dans le forum Programmation et langages, Algorithmique
    Réponses: 1
    Dernier message: 08/04/2013, 19h43
  4. Autre source d'énérgie
    Par invitef5c47ebc dans le forum Environnement, développement durable et écologie
    Réponses: 42
    Dernier message: 08/06/2011, 23h44
  5. Ouvrir fichier dans application déjà ouverte - Instance unique
    Par lignux dans le forum Logiciel - Software - Open Source
    Réponses: 9
    Dernier message: 15/01/2009, 18h06