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

Langage C++ Discussion :

Le mot clé "Internal" de C# en C++


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2007
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 73
    Par défaut Le mot clé "Internal" de C# en C++
    Bonjour à tous,

    Voila je m'initie au fur et à mesure au dev C++ et venant de C#, j'ai beau avoir cherché comme un forconé, je n'arrive pas à trouver ou même à reproduire l'effet du mot-clef "internal" qui à l'énorme avantage de proposer les élément apposé de par ce mot clef uniquement visible dans le namespace.
    Il est vrai que 3 choix intermédiaire se propose:
    * mettre tout en public au point de rendre public des éléments qui ne devrait pas l'être.
    * utiliser un sous-package mais ceci ne fonctionnne pas si l'on souhaite mettre la classe publique avec des fonctions privées.
    * Utiliser du friend à outrance avec tout ce qui devrait être internal en privé/protected et c'est la solution que j'ai choisit actuellement qui commence réellement à être bouffante et chiante. Surtout qu'il n'est même pas possible de faire un "friend namespace".

    Bref, j'aimerais connaitre les solutions les plus viables pour palier à cet ENORME manque.

    D'avance merci,
    Lucyberad.

  2. #2
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Salut!

    Je pense qu'il va falloir que tu revoies totalement comment une application C++ est organisée car tu peux oublier la notion de package. #include n'a rien a voir avec import et les namespaces n'ont pas le même effet en C++ qu'en C#/Java/ActionScript.

    Il n'y a pas d'equivalent d'internal en C++ parcequ'il n'y a pas de package en C++.
    Un namespace est avant tout un "nom" qui servira de prefix automatique pour tout ce qui est dans le namespace, vraiment rien de plus. Tu peux déclarer n'importe où le contenu d'un namespace en C++ : c'est un concept orthogonal à la façon d'organiser les fichiers (ce qui n'est pas le cas avec les packages). De la même façon, tu peux mettre n'importe quoi dans tes fichiers, même un programme entier dans un unique cpp si ça te chante. En C++, tu organises les fichiers de la manière que tu veux. La seule contrainte est que quand tu compiles un cpp, il doit contenir au moins les déclarations de tous les symboles (variables, classes, etc) qui sont utilisés dans le cpp. C'est pour cela qu'on inclus les fichiers (les headers) qui détiennent ces déclarations. Une fois le cpp compilé, le linker va faire le lien entre les déclarations et les définitions manquantes, qui sont (ou pas) définies dans d'autres cpp.

    Maintenant dans ton cas, tu veux en gros que l'implémentation de ton application ou module ne soit pas accessible à l'utilisateur. C'est exact? De loin, je dirais qu'il faurait utiliser l'idom "pimpl" mais je ne suis pas certains que ce soit ce que tu veux faire.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    A vrai dire, je me pose la question de savoir si tu en as vraiment besoin...


    Je m'explique:

    D'abord, est-il *réellement* de notre ressort de décider, à partir du moment où l'on a décidé d'exposer une classe, un comportement ou une fonction libre, de l'endroit à partir duquel il est possible d'y accéder

    Ensuite, si tu respecte un tant soit peu demeter, et que tu veilles déjà à ce que chaque classe n'expose pas plus que le stricte nécessaire pour qu'elle puisse fournir les services que l'on peut attendre d'elle, tu arrive déjà à un point où, finalement, tu peux clairement ne pas t'inquiéter de l'endroit à partir duquel le service est appelé.

    Après tout, le but d'un espace de noms est, tout simplement, de "regrouper entre eux" les différents éléments qui "travaillent bien ensemble".

    De plus, la compilation sous la forme d'unité de compilation (un fichier d'en-tête + un fichier d'implémentation) te permet, si tu sépare correctement les définitions des différentes classes et que tu veille à n'inclure dans un fichier d'en-tête que le stricte minimum en préférant, chaque fois que faire se peut, la déclaration anticipée, te donne parfaitement le moyen de permettre l'utilisation d'une classe sans, pour autant, permettre à l'utilisateur d'utiliser un autre type qui ne sert qu'à titre d'argument de fonction, par exemple.

    Enfin, il faut savoir qu'une structure imbriquée n'est accessible que selon l'accessibilité dans laquelle elle est déclarée.

    Ainsi, si tu as besoin d'une structure qui n'a strictement pas vocation à être exposée pour un usage strictement interne, tu peux la déclarer dans une accessibilité privée et "le reste du programme" en ignorera jusqu'à l'existence (cela va d'ailleurs encore plus loin car il est possible de définir une classe ou une structure à l'intérieure même d'une fonction... Elle n'est alors utilisable que dans cette fonction particulière)

    Et tu peux même envisager, pour "compléter le tableau", de ne faire qu'une déclaration de la structure imbriquée dans la définition de la structure qui l'emploie, et de définir la structure imbriquée que... dans le fichier d'implémentation, avec cependant les restrictions d'usages pour les déclarations anticipées (il ne doit être question de la structure imbriquée que sous forme de pointeur ou de référence jusqu'à ce que la définition réelle soit apparue dans le code).
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Février 2007
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 73
    Par défaut
    Là encore, j'ai bien compris le concept de la déclaration dans le CPP (et non le .h) et les nested class ou nested function.

    Il est vrai que dans l'absolu, une classe qui partage une moitié publiquement et une autre seulement au namespace peut en toute théorie se permettre de montrer le tout à tout le monde car une classe doit être autonome. Néanmoins, c'est toujours mieux de faire cette "formalisation" qui permet de clairement délimiter les pouvoirs de celui qui l'utilise.
    Dans mon cas, je vais quand même plus loin car l'ensemble de mes classes sont destinées à un framework et certaines méthodes sont clairement destinées à un usage interne au framework. Je vois donc clairement une classe comme un composant intégré à un framework dont le package/namespace sert à en donner les limites. Après tout, le package comme je le pense est un objet auquel un autre package objet fait appel.
    Or, le namespace comme tu dit n'est que structuration du code n'influant en rien sur la visibilité de ce qui le compose.
    En demandant l'internal, je pense donc avant tout à l'exemple suivant: prenons le cas d'une entreprise; les patrons et employés sont dans la même entreprise mais il parait logique que le patron soit le seul à avoir accès à la signature des contrats avec le client extérieur. Un client communiquant direct avec un technicien pour la signer un contrat peut mettre à mal l'entreprise pour avoir entrepris une production contrôlée et désirée sauf si on a validé ce technicien comme apte à recevoir les clients.
    Je trouve juste un petit peu dommage que le "croulant de vieillesse" C++ soit plutôt réfractaire à ce point, mais bon: je vais faire avec...

    J'ai pensé à la solution de l'objet public (pimpl), mais en gros ca double tout les objets pour rien et alourdi le tout, même si ca me permettrait symboliquement d'obtenir ce que je souhaite.

    Merci de vos infos,
    Lucyberad.

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Mais ce qu'il faut comprendre, c'est que, si tu as une (ou plusieurs) classe(s) qui ne servent qu'à usage interne dans ton espace de noms, en organisant "correctement" tes en-têtes et tes inclusions, il t'est tout à fait possible de "simplement" ne pas exposer le fichier d'en-tête dans lequel elle(s) est(sont) déclarée(s)...

    Le résultat immédiat sera que celui qui utilisera ton framework ignorera purement et simplement l'existence de cette (ces) classe(s), ou, du moins, sera dans l'impossibilité totale de l'utiliser...

    Cela ne t'oblige absolument pas à "doubler" tes objet, cela t'oblige "seulement" à implémenter les choses différemment.

    Par exemple, tu peux parfaitement envisager une première classe proche de
    fichier MaClassPrivee.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #ifndef MACLASSPRIVEE_H
    #define MACLASSPRIVEE_H
    namespace MonEspaceDeNoms
    {
        class MaClassPrivee
        {
            public:
                MaClassPrivee(int i, int j){}
        };
    } // namespace MonEspaceDeNoms
    #endif
    Si tu as besoin de cette classe de manière uniquement interne, tu peux parfaitement l'utiliser sous la forme de
    fichier AutreClass.h
    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
    #ifndef AUTRECLASS_H
    #define AUTRECLASS_H
    namespace MonEspaceDeNoms
    {
        class MaClassPrivee; // juste une déclaration anticipée
        class AutreClass
        {
            public:
                AutreClass(int i, int j);
                ~AutreClass();
           private:
               MaClassPrivee * pm_;
        };
    } // namespace MonEspaceDeNoms
    #endif
    fichier AutreClass.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include "MaClassPrivee.h"
    #include "AutreClass.h"
    namespace MonEspaceDeNoms
    {
    AutreClass::AutreClass(int i, int j):pm_(new MaClassPrivee(i,j)){}
    AutreClass::~AutreClass()
    {
        delete pm_;
    }
    } // namespace MonEspaceDeNoms
    Tu peux inclure le fichier MaClassPrivee.h dans n'importe quel fichier d'implémentation qui aura besoin de cette classe (éventuellement avec une déclaration anticipée dans le fichier d'en-tête correspondant), et, pour autant que tu ne fournisse pas le fichier MaClassPrivee.h aux utilisateurs, tu as, de facto, limité l'utilisation de cette classe au développement de ton framework
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Je trouve juste un petit peu dommage que le "croulant de vieillesse" C++ soit plutôt réfractaire à ce point, mais bon: je vais faire avec...
    Il est plus probable que tu n'aies pas compris qu'en C++ il n'y a pas besoin de mot clé pour "cacher" du code (ne pas le rendre accessible au code client), comme l'a expliqué koala01. Le mot clée internal est apparu dans les langages a package pour combler le fait que ce problème n'était pas résolvable, alors qu'en C++ il n'y a tout simplement rien a ajouter, il suffit d'organiser son code en conséquence. La structure même du code donne l'accessibilité (au dela des private/public/protected/friend).
    Mais j'imagine que tant qu'on ne comprends pas comment faire, ça n'a rien d'evident.

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Klaim Voir le message
    Il est plus probable que tu n'aies pas compris qu'en C++ il n'y a pas besoin de mot clé pour "cacher" du code (ne pas le rendre accessible au code client), comme l'a expliqué koala01. Le mot clée internal est apparu dans les langages a package pour combler le fait que ce problème n'était pas résolvable, alors qu'en C++ il n'y a tout simplement rien a ajouter, il suffit d'organiser son code en conséquence. La structure même du code donne l'accessibilité (au dela des private/public/protected/friend).
    Mais j'imagine que tant qu'on ne comprends pas comment faire, ça n'a rien d'evident.
    J'irais presque plus loin en disant que si ce mot est devenu nécessaire en C#, c'est parce qu'ils ont commis la bêtise (tout comme ne java, d'ailleurs) de vouloir rassembler la définition des classes et l'implémentation de leurs fonctions membre.

    Bien sur, il y a "à boire et à manger" dans cette décision, car, effectivement, cela peut apporter comme avantage de ne plus *forcément* recourir à un préprocesseur pour effectuer le regroupement à notre place, et l'on peut imaginer que cela facilite le travail du compilateur (ou de la machine virtuelle), ou encore, il faut avouer que cela permet de ne plus avoir qu'un fichier par unité de compilation à gérer...

    Mais, à coté de cela, cela occasionne plusieurs problèmes connexes, comme le fait que, tout le code se trouvant dans un même fichier, il devient de facto beaucoup plus volumineux ou celui qu'il devient impossible de limiter l'accès à une classe donnée à un nombre restrient d'unités de compilaton.

    Encore une fois, voici bien la preuve que rien n'est gratuit en informatique, et que la plupart des décisions prises font souvent perdre d'un coté ce qu'elle font gagner de l'autre
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

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