Peut-on temporairement changer, dans son propre code source un "specifier d'accès", par exemple 'private' en 'public' ?
Peut-on temporairement changer, dans son propre code source un "specifier d'accès", par exemple 'private' en 'public' ?
Bonsoir,
non c'est fixé à la compilation
après y'a la bidouille, mais le besoin est des plus étranges..
Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
Un peu de programmation réseau ?
Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.
Avant que koala01 n'arrive et n'écrive 100 lignes sur ce topic , j'ai simplement envie de te dire que si tu en viens à te poser cette question, c'est peut-être parce que tu as un problème de conception dans tes classes.
Si vous ne savez toujours pas ce qu’est la récursivité, relisez cette phrase.
Mon blog sur la programmation et l'informatique !
Bonsoir,
Tu peux mettre en friend des classes/fonctions qui doivent accéder aux membres privates (mais il ne faut pas en abuser).
Si tu as besoin d'avoir une phase de construction de ton objet avant qu'il soit pleinement opérationnel tu peux utiliser des pattern design ( factory ?)
Est-ce que tu recherches à faire quelque chose en particulier ?
Le problème est le suivant : c'est une petite encapsulation de libXml avec les classes suivantes :
Dans le .cpp :
et dans le .h :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 class XmlDoc_Impl { public: libXmlDoc _doc; }; class XmlNode_Impl { public: libXmlNode _node; XmlDoc& docRef; // fait référence au document global };
et donc il arrive que le XmlNode ait besoin d'accéder à la partie 'private' _impl du XmlDoc (pour créer un nouveau noeud par exemple.)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 class XmlDoc { private: XmlDoc_Impl* _impl; }; class XmlNode { private: XmlNode_Impl* _impl; };
Cdlt.
Une amitié me semble une assez bonne solution.
L'autre serait que le node est une référence non pas vers un doc, mais vers son implémentation...
Mes principes de bases du codeur qui veut pouvoir dormir:Pour faire des graphes, essayez yEd.
- Une variable de moins est une source d'erreur en moins.
- Un pointeur de moins est une montagne d'erreurs en moins.
- Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
- jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
- La plus sotte des questions est celle qu'on ne pose pas.
le ter nel est le titre porté par un de mes personnages de jeu de rôle
XmlNode ne devrait pas accéder à la partie private du XmlDoc mais utiliser l'interface de XmlDoc.
Une méthode AddNode est totalement justifiée et je m'attendrais à en trouver une comme utilisateur. Même son absence me surprendrait !
Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
Un peu de programmation réseau ?
Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.
Damn... Je suis fait
Mais, cette question se rapproche, finalement, très fort de cette discussion qui a précédé un bien long débat, il y a à peu près deux ans
Bien sur, j'ai peut etre une meilleure vision des choses qu'à l'époque, mais je maintiens malgré tout ce que disais pour l'occasion (exception faite de quelques détails concernant la programmation par contrat )
Peut etre ces deux discussions aideront-elles à convaincre foulques.nera (et tout autre intervenant) qu'il y a bel et bien un problème de conception à la base
PS: si vous voulez cent lignes et plus, je suis partant
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
[FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.
Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.
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
Iiiiiiiiicks. (1)
Par quel miracle ? (ok, je suis moyen diplomate là. Désolé ).
L'API libxml2 offre toutes les fonctions qu'il te faut pour créer un nouveau noeud. Nulle part tu n'a besoin d'aller chercher des infos sur le document - et si tu as ce besoin, alors la fonction de création de noeud est situé dans l'objet document. Ou, alternativement, tu peux récupérer le document en utilisant le membre ->doc de ton instance de XmlNode parent - ce qui ne nécessite pas l'objet document lui-même, et ce qui n'est pas nécessairement une Bonne et Grande Chose.
Ecrire une lib XML en C++ n'est pas spécialement complexe (au niveau architecture ; au niveau du code, ça dépends de la lib ; mais si on se focalise sur les parseurs DOM comme la libxml2 ou roxml ou encore ezxml, ça reste simple ; un parseur d'un autre type (tel que le parseur SAX de expat) peut être un poil plus subtil, encore qu'il soit tout à fait possible de ramener ce type de parseur à un parseur DOM).
Qui plus est, réécrire une encapsulation de la libxml2, alors qu'il existe la libxml++, c'est dommage. Ceci dit, je peux comprendre (cette lib utilise un paradigme qui n'est pas très moderne).
--
(1) je me demandais quelle était l'utilisation de ce smiley.
[FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.
Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.
Bon, ben, tu l'auras voulu...
Fallait pas me mettre au défi
Pour commencer, je dirais que la questionmériterait d'être subdivisée en deux questions distinctes:Peut on changer, dans son propre code source un "specifier d'accès"?
En première analyse (donc, uniquement d'un point de vue purement conceptuel), la réponse à la première question est:
- Peut on (temporairement) augmenter l'accessibilité d'un membre ou d'une fonction ? et
- Peut on (temporairement) réduire l'accessibilité d'un membre ou d'une fonction ?
Rien ne l'interdit a priori, mais est-il réellement cohérent de le faire
Je m'explique:
Conceptuellement parlant, il n'est pas impensable de se dire qu'une fonction privée ou protégée puisse, dans une classe dérivée, passer en accessibilité publique : Le LSP est clairement respecté (toutes les propriétés valides de la classe de base restent valides dans la classe dérivée), et l'on ne fait "qu'étendre" l'interface de la classe dérivée.
Cependant, on peut clairement se poser la question de l'intérêt qu'il peut y avoir à le faire:
Typiquement, le concepteur d'une classe est sensé savoir exactement à quoi elle va servir, quelles possibilités d'évolutions sont envisageables.
On peut estimer que le concepteur savait exactement ce qu'il faisait en définissant un(e fonction) membre comme "à usage interne" uniquement (dans le cas de l'accessibilité privée) ou comme "à usage de la classe de base et de ses dérivées uniquement" (dans le cas de l'accessibilité protégée.
Il s'agira alors d'avoir des raisons vachement bonnes pour accepter l'idée que, finalement, ce(tte fonction) membre puisse être "disponible depuis n'importe où" dans les classes dérivées.
Je n'ai, personnellement, pas encore croisé de cas où cela se justifierait, mais je reste ouvert à la discussion et je peux concevoir que cela puisse s'avérer utile / intéressant dans certaines circonstances.
Après tout, le propre des fonctions membres publiques est quand même de fournir un accès, fusse-t-il restreint, à des éléments se trouvant dans les accessibilités restreintes, alors, pourquoi ne pourrait-on pas envisager de "simplement" diminuer les restrictions
Le fait de passer d'une accessibilité privée (ou protégée) à une accessibilité publique ne présenterait qu'un effet similaire
Par contre, pour la partie "peut on restreindre l'accessibilité d'un(e fonction) membre", là, je ne peux que m'écrier "attention, danger, problème de conception!!!"
D'un coté, il y a, selon moi, violation flagrante du principe de substitution de liskov, de l'autre, on peut très facilement justifier le fait qu'il y a un problème en terme de programmation par contrat, mais vous vous rendrez compte dans les lignes qui suivent que les deux sont particulièrement imbriquées.
En effet, le Principe de Substitution de Liskov dit que toute propriété valide d'un objet t de type T doit être valide pour tout objet s de sous type S, tel que S est sous type de T (AKA hérite publiquement de T).
Encore faut il se mettre d'accord sur ce que représente ce "toute propriété valide"...
Ma thèse est que tout ce qui fait partie de l'interface publique du type de base est à considérer comme une propriété valide pour ce type.
A ce titre, le fait de faire passer une fonction membre ("foo" pour l'exemple) de l'accessibilité publique dans la classe parent à une accessibilité moindre dans la classe dérivée fait que la propriété "dispose de la fonction foo" qui est vraie (valide) pour la classe de base devient fausse (invalide) pour la classe dérivée.
Liskov n'étant pas respecté, l'héritage ne peut pas se faire.
Et là, il est temps de rappeler que le LSP est un principe de conception: c'est à dire que c'est un principe qui va servir de "GO / NO GO" bien avant même de prendre en compte le langage dans lequel dans lequel l'héritage sera mis en oeuvre, et donc, bien avant même d'écrire la première ligne de code.
En effet, quel que soit le langage (orienté objets quand même) que l'on pourra envisager, aucun langage ne pourra faire qu'une mauvaise décision de conception (l'héritage publique en l'occurrence) puisse "comme par magie" devenir une bonne décision "simplement" parce que le langage n'est pas armé pour évaluer la décision du développeur.
Par contre, le langage utilisé devra être pris en compte directement après LSP, mais uniquement si LSP est respecté, car certains langages (je pense entre autres à java) imposent des restrictions à ce que les principes OO permettent (je pense, par exemple, à l'héritage multiple).
Ainsi, il faut bien comprendre que ce n'est pas parce que le langage accepte une décision de conception incohérente que la décision en elle-même devient valide conceptuellement parlant...
Après tout, en C++, un code proche de
compilera sans aucun problème, mais, pour ce qui est de l'exécution, on se rend compte qu'il nous fournira une sortie proche de
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
25
26
27 class Base { public: vritual void foo() { std::cout<<"cette fonction est a usage public"<<std::endl; } }; class Derived : public Base { protected: vritual void foo() { std::cout<<"cette fonction est a usage interne uniquement"<<std::endl; } }; void bar(Base & b) { b.foo(); } int main() { Derived d; // d.foo(); refusé à la compilation bar(d); // accepté à la compilation return 0; }
et l'on se rend compte qu'il est pour le moins illogique d'avoir un tel comportement, qui nous dit explicitement que la fonction est à usage unique.
Code : Sélectionner tout - Visualiser dans une fenêtre à part cette fonction est a usage interne uniquement
Le problème, en l'occurrence, c'est que le compilateur n'est pas armé pour vérifier s'il est ou non opportun d'envisager l'héritage et qu'il agira donc comme un "bon petit soldat" en faisant exactement ce qu'on lui demande de faire.
Et contre, comme l'accessibilité ne sert qu'au niveau de la compilation, et qu'on a été "assez idiot" pour perdre dans bar le fait que l'on ne travaille pas avec un objet dont le type (dynamique) Base mais bien avec un objet dont le type (dynamique toujours) est Derivee, le compilateur n'a plus aucun moyen de vérifier si foo est, effectivement, disponible ou non.
Nous sommes donc face à une décision que le langage (et le compilateur) va accepter sans problème, mais qui n'aurait jamais du être prise du point de vue de la conception, ce que le LSP nous l'aurait fait remarqué si on avait appliqué "en temps utiles".
Dans d'autres cas, les langages imposent des restrictions par rapport aux principes OO :
Rien n'empêche, conceptuellement parlant, d'envisager qu'un TorboGenerateur hérite publiquement (sous la forme d'un héritage multiple) d'une Turbine et d'une Generatrice parce que c'est, bel et bien un objet qui présentera toutes les propriétés d'une turbine et toutes celle d'une génératrice, mais, vu que java (entre autres) interdit l'héritage multiple, bien que LSP soit respecté et nous ait donné un "GO" pour l'héritage, il faudra quand même envisager une solution différente, uniquement parce que le langage ne permet pas l'héritage multiple.
[EDIT] C++ permettra quant à lui un tel héritage multiple, et le concepteur n'aura pas à faire le choix (cornélien s'il en est) entre hériter de Générateur et implémenter l'interface de Turbine ou, à l'inverse, hériter de Turbine et implémenter l'interface de Générateur.
Tout cela pour dire que, bien que le langage cible doive être pris en considération au moment d'envisager l'héritage, il ne devra l'être qu'après que la décision d'y recourir ait été validée par le LSP
Et, comme ma thèse est que l'ensemble de l'interface publique de la classe parent représente l'ensemble des propriétés valides de celle-ci, le fait qu'une des fonctions publiques de la classe parent ne soit plus directement accessible dans les même conditions (comprenez : depuis n'importe où dans le code où l'on utiliserait un objet connu pour être du type dérivé) fait qu'une propriété valide pour la classe de base ne sera plus valide pou la classe dérivée.
De ce fait, LSP nous donnerait un "NO GO" en ce qui concerne la relation d'héritage.
Il y aurait, bien sur, moyen de contourner le problème en créant une autre classe de base ne présentant pas la fonction dont on veut restreindre l'accessibilité et de faire hériter aussi bien la classe avec la fonction publique que la classe avec la fonction protégée (ou privée) de cette classe de base, et donc de faire en sorte que ces deux classes (celle qui a la fonction publique et celle qui a la fonction protégée / privée) soient des soeurs / des cousines, mais il ne peut pas être question d'un héritage, du moins si la classe de base expose la fonction sous sa forme publique.
Considérons maintenant l'aspect de la programmation par contrat...
Comme je l'ai dit, vous verrez que le raisonnement est fort proche de celui que j'ai suivi pour le LSP, et c'est normal, parce que je vais me baser sur des corollaires au LSP...
En programmation par contrat, on nous dit que, si on envisage l'héritage publique, les règles suivantes sont d'application:
Pour ma thèse, je vais me baser uniquement sur les invariants.
- Les préconditions ne peuvent pas être renforcées dans le sous type (la classe dérivée)
- les postconditions ne peuvent pas être allégées dans le sous type
- les invariants doivent être respectés dans le sous type
Selon wikipedia, un invariant est
On peut donc considérer que pour toute fonction publique de la classe de base, il existe un invariant "dispose de la fonction publique <nom de la fonction>" qui est égal à ... vrai...une condition qui est toujours vraie. Selon le type d'invariant, cette assertion caractérise l'état interne de tout le programme, ou seulement d'une partie comme par exemple pour un invariant de boucle ou un invariant d'objet.
Si, dans la classe dérivée, on fait en sorte de "cacher" cette fonction en en réduisant l'accessibilité, l'invariant correspondant vaut alors... faux, et l'invariant n'est donc pas respecté.
Mais, encore une fois, il s'agit de quelque chose qui doit être évalué avant même de réfléchir à ce que permet (ou non) le langage, car c'est toujours une vérification qui doit être effectuée en cours de... conception.
Encore une fois, aucun langage n'est armé pour s'assurer qu'une décision de conception est bel et bien opportune.
Si vous décidez, bien que cela n'ait aucun sens conceptuellement parlant, de faire hériter votre classe "Cuiller" d'une classe "Vehicule", aucun langage ne pourra vous faire savoir que vous n'auriez pas du envisager cette relation d'héritage.
Et si vous le faites, il ne faudra pas vous étonner d'être en mesure de... démarrer votre cuiller, quoi que cela puisse vouloir dire
PS Ca ne fait peut etre pas cent lignes d'intervention, mais je dois quand même m'en approcher pas mal, non
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
100 lignes tout rond sur mon écran, pas de doute il est vraiment très fort
super explication au passage
Si vous ne savez toujours pas ce qu’est la récursivité, relisez cette phrase.
Mon blog sur la programmation et l'informatique !
Parce qu'il les as compté, le fouSi tu relis le débat d'il y a deux ans, tu constateras très certainement une très forte corrélation avec ce que je disais à l'époque.super explication au passage
J'ai, essentiellement, regroupé mon argumentaire de manière à dire tout ce qu'il fallait sur le sujet d'un seul coup (en espérant ne pas relancer un débat similaire )
Mais ca fait plaisir quand meme Merci
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
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager