Puis-je accéder aux membres privés de l'extérieur de la classe, sans l'aide d'amis?
Avertissement
Oui, je suis pleinement conscient que ce que je demande est totalement stupide et que toute personne qui souhaiterait essayer une telle chose dans le code de production devrait être congédié et/ou de la grenaille. Je suis principalement à la recherche pour voir si peut être fait.
Maintenant que c'est de la manière, est-il possible de l'accès privé aux membres de la classe en C++ à partir de l'extérieur de la classe? Par exemple, est-il possible de faire cela avec les compensations pointeur?
(Naïve et non prêt pour la production des techniques de bienvenue)
Mise à jour
Comme indiqué dans les commentaires, j'ai posé cette question parce que je voulais écrire un billet de blog sur over-encapsulation (et comment il affecte TDD). Je voulais voir si il y avait une façon de dire "à l'aide de variables privées n'est pas 100% fiable pour faire respecter l'encapsulation, même en C++." À la fin, j'ai décidé de se concentrer davantage sur la façon de résoudre le problème plutôt que de savoir pourquoi c'est un problème, donc je n'ai pas les choses apportées jusqu'ici en bonne place comme je l'avais prévu, mais j'ai toujours laissé un lien.
En tout cas, si quelqu'un est intéressé par la façon dont il est sorti, c'est ici: Les ennemis de Développement Piloté par les tests de la partie I: l'encapsulation (je suggère de le lire avant de vous décider que je suis fou).
- D'intérêt, pourquoi poser la question. La seule utilisation que je peux penser pour ce qui est de pirater quelqu'un elses API pour faire des ravages.
- Je suis en train d'écrire un billet de blog sur over-encapsulation. Je viens de regarder pour voir si il était possible de dire "la protection par des méthodes privées n'est pas parfait, même en C++!" Je vais poster le lien une fois que j'ai obtenu il écrit.
Vous devez vous connecter pour publier un commentaire.
Si la classe contient toutes les fonctions membres de modèle vous pouvez vous spécialiser cette fonction membre pour répondre à vos besoins. Même si le développeur n'a pas penser à elle.
coffre-fort.h
main.cpp:
De sortie:
J'ai ajouté un l'entrée de mon blog (voir ci-dessous) qui montre comment il peut être fait. Voici un exemple sur la façon dont vous l'utilisez pour la classe suivante
Il suffit de déclarer une structure pour l'endroit où vous le décrire et l'instanciation de la classe d'implémentation utilisée pour vol
La
Rob
modèle de classe est définie comme ceci, et ne doit être défini une fois, quel que soit le nombre de membres privés vous envisagez d'accéder àToutefois, cela ne montre pas que le c++de règles d'accès ne sont pas fiables. Les règles de la langue sont conçus pour protéger contre les chocs, les erreurs - si vous essayez de voler les données d'un objet, la langue de par sa conception ne prend pas de détours pour vous empêcher de vous.
template struct Rob<A_member, &A::member>;
C'est un modèle explicite de l'instanciation de classe.&A::member
travaille ici car: "instanciation Explicite définitions ignorer membre spécificateurs d'accès: les types des paramètres et le type de retour peut être privé"a.*get(A_member())
appels non-membre ami de la fonctionget(A_member)
qui renvoie&A::member
. Cela fonctionne parce que des "ami injection". Essayez de supprimer le terme "inutile" l'argument de la get() et la fonction, vous devriez obtenir "get n'a pas été déclarée dans ce champ" (je voudrais voir une explication concise de ce comportement).A::member
n'est pas unint
, mais unenum Foo
où le nomFoo
est privé dansA
?La suite est sournois, illégal, compilateur-dépendante, et peut ne pas fonctionner selon différents détails de mise en œuvre.
Mais c'est une réponse à votre OP, dans lequel vous inviter de manière explicite une technique qui, et je cite, "est totalement stupide et que toute personne qui souhaiterait essayer une telle chose dans le code de production devrait être congédié et/ou de la grenaille".
Une autre technique consiste à accès privé des données sur les membres, par contructing pointeurs à l'aide codée en dur/codée à la main les décalages à partir du début de l'objet.
Hmmm, je ne sais pas si ça allait fonctionner, mais peut être vaut la peine d'essayer. Créer une autre classe avec la même mise en page que l'objet avec les membres privés mais avec privé changé pour le public. Créer une variable de pointeur vers cette classe. Utiliser une distribution simple à ce point votre objet avec les membres privés et essayez d'appeler une fonction privée.
S'attendre à des étincelles et peut-être un accident 😉
Cela devrait le faire.
ETA: Il va travailler pour ce genre de trivial de classe, mais comme une chose générale, il ne sera pas.
Alors on se retrouve avec le meilleur pari est de déclarer
class B
pour correspondre àA
's layout et hack pour regarder une classe de soldats.Si vous pouvez obtenir un pointeur vers un membre d'une classe, vous pouvez utiliser le pointeur peu importe ce que les spécificateurs d'accès (même méthode).
Bien sûr, mon petit favori hack est l'ami de modèle de porte arrière.
En supposant que le créateur de la ci-dessus a défini une porte dérobée pour ses utilisations normales. Mais vous voulez accéder à l'objet et regardez les variables de membre privées. Même si la classe ci-dessus a été compilé dans une bibliothèque statique, vous pouvez ajouter votre propre modèle de spécialisation pour backDoor, et donc l'accès aux membres.
Il est certainement possible d'accéder aux membres privés avec un offset du pointeur en C++. Supposons que j'avais la suite de la définition de type que je voulais accéder à.
S'il n'y a pas de méthodes virtuelles dans un Bar, Le cas simple est _m1. Membres en C++ sont stockées comme des décalages de l'emplacement de mémoire de l'objet. Le premier objet est à la position 0, le deuxième objet au décalage de sizeof(premier membre), etc ...
Voici donc un moyen d'accéder à _m1.
Maintenant _m2 est un peu plus difficile. Nous avons besoin de déplacer le pointeur d'origine sizeof(SomeOtherType) octets à partir de l'original. Le casting de personnage est de s'assurer que je suis l'incrémentation dans un décalage d'octet
cool question btw... voici mon morceau:
Espère que cette aide.
Cette réponse est fondée sur le concept exact démontré par @Johannes réponse/blog, comme cela semble être le seul "légitime" de manière. J'ai converti l'exemple de code dans un utilitaire pratique. Il est facilement compatible avec le C++03 (par la mise en œuvre de
std::remove_reference
& remplacernullptr
).Bibliothèque
API
Utilisation
Exemple
enum Foo
oùFoo
était aussi dans la section privée, parce queClass::Foo
ne peut pas être utilisé dans leALLOW_ACCESS
macro en raison d'être privé! Toutes les suggestions?Si vous savez comment le compilateur C++ mangles noms, oui.
Sauf, je suppose, c'est une fonction virtuelle. Mais alors, si vous savez comment votre compilateur C++ construit la VTABLE ...
Edit: en regardant les autres réponses, je me rends compte que j'ai mal lu la question et pensé qu'il était sur les fonctions de membres, pas de données sur les membres. Toutefois, le point est toujours debout: si vous savez comment votre compilateur dispose de données, alors vous pouvez accéder à ces données.
Il est en fait assez facile:
Comme une alternative au modèle de porte dérobée de la méthode, vous pouvez utiliser un modèle de porte dérobée de la classe. La différence est que vous n'avez pas besoin de mettre cette porte dérobée classe en zone publique de la classe de votre allons tester. J'utilise le fait que de nombreux compilateurs permettent classes imbriquées pour accéder à la zone privée de la classe englobante (qui n'est pas exactement 1998 standard mais considérés comme étant "de droite" comportement). Et bien sûr, en C++11 c'est devenu légal comportement.
Voir cet exemple:
À côté de #define privé public vous pouvez également #define protégées privées et ensuite définir une classe foo comme descendant de voulu classe pour y avoir accès (maintenant protégées) méthodes via la conversion de type.
tout simplement créer votre propre accès à la fonction membre pour étendre la classe.
À toutes les personnes en suggérant "#define privé public":
Ce genre de chose est illégale. La norme interdit de la définition du fnud-ing macros qui sont lexicalement équivalent à réservés les mots clés du langage. Alors que votre compilateur ne sera probablement pas se plaindre (je n'ai pas encore vu un compilateur qui n'), il n'est pas quelque chose qui est une "Bonne Chose" à faire.
"à l'aide de variables privées n'est pas 100% fiable pour faire respecter l'encapsulation, même en C++."
Vraiment? Vous pouvez démonter la bibliothèque dont vous avez besoin, trouvez tous les décalages nécessaires et de les utiliser.
Qui vous donnera la possibilité de modifier à tout membre privé que vous aimez... MAIS!
Vous ne pouvez pas accéder aux membres privés sans une sale de piratage.
Permettez-nous de dire que l'écriture const ne fera pas votre constante d'être vraiment constante, parce que vous pouvez
cast const ou tout simplement utiliser l'adresse de l'invalider. Si vous êtes à l'aide de MSVC++ et que vous avez spécifié "-fusion:.rdata=.les données" pour un éditeur de liens, l'astuce fonctionne sans aucun accès à la mémoire de défauts.
On peut même dire que l'écriture d'applications en C++ n'est pas fiable pour écrire des programmes, parce que résultant code bas-niveau peut être corrigée à partir de quelque part à l'extérieur lorsque votre application est en cours d'exécution.
Alors qu'est-ce que fiable documenté de façon à respecter l'encapsulation? Peut-on cacher les données quelque part dans la mémoire RAM et d'empêcher tout accès à l'exception de notre code? La seule idée que j'ai est de chiffrer les membres privés et de les sauvegarder, parce que quelque chose peut corrompre les membres.
Désolé si ma réponse est trop impoli, je ne veux pas offenser personne, mais je ne pense vraiment pas que la déclaration est sage.
puisque vous avez un objet de classe je suppose que vous avez de la déclaration de la classe.
Maintenant, ce que vous pouvez faire est de déclarer une autre classe, avec les mêmes membres, mais gardez tout de spécificateurs d'accès public.
Par exemple précédent, la classe est:
vous pouvez déclarer une classe comme
Maintenant tout ce que vous devez faire est de cast pointeur de classe
Iamcompprivate
dans un pointeur de classeNowIampublic
et de les utiliser comme U le souhaitez.Exemple:
Par le référencement *ce vous activez une porte dérobée pour toutes les données privées à l'intérieur d'un objet.
Assez souvent une classe mutateur méthodes à des données privées (getters et setters).
Si une classe permet de fournir un getter qui renvoie une référence const (mais pas de setter), alors vous pouvez simplement const_cast la valeur de retour de la lecture, et de l'utiliser comme un l-valeur:
J'ai utilisé une autre approche utile (et la solution) pour accéder à une c++ privé/protégé membre.
La seule condition est que vous êtes en mesure d'hériter de la classe à laquelle vous souhaitez accéder.
Puis tout le crédit va à reinterpret_cast<>().
Un problème possible est que cela ne fonctionnera pas si vous insérez une fonction virtuelle, qui va modifier la table virtuelle, et donc, la taille de l'objet/l'alignement.
Ensuite, vous avez juste besoin d'utiliser la classe comme suit:
Mon problème d'origine était comme suit: j'ai besoin d'une solution qui ne signifie pas recompiler les bibliothèques QT.
Il existe 2 méthodes de QObject, dumpObjectInfo() et dumpObjectTree(), qui
travail juste si QT libs sont compilé en mode debug, et ils ont besoin de l'accès à d_ptr proteted membre (parmi d'autres structures internes).
Ce que j'ai fait a été d'utiliser la solution proposée pour ré-écrire (avec le copier-coller) ces méthodes de dumpObjectInfo2() et dumpObjectTree2() dans ma classe (QObjectWrapper), la suppression de ces debug preprocesor gardes.
Le code suivant accède et modifie un membre privé de la classe à l'aide d'un pointeur vers la classe.
but de l'étude seulement....
essayez ceci ....peut être utile je pense.....
ce programme peut accéder aux données privées juste en sachant les valeurs...
Inspiré par @Johannes Schaub - litb, le code suivant peut être un peu plus facile à digérer.
méthode A : intrusif de l'humeur.
depuis qu'on a accès au code source et recomplie, nous pouvons utiliser
beaucoup d'autres comme ami de la classe pour accéder membre privé, ils sont tous des backdoor.
méthode B : brute de l'humeur.
nous utilisons un nombre magique (20) , et Il n'est pas toujours droit. Lors de la mise en page de la classe de Test changé, le nombre magique est un gros bug source.
méthode C : super hacker humeur.
est-il un non-intrusive et non-brute de l'humeur ?
depuis la classe de Test de mise en page de l'information est cacher par le compilateur,
nous ne pouvons pas obtenir des informations d'offset de la complie de la bouche.
ex.
nous aussi ne peut pas obtenir pointeur de membre de la classe de Test.
ex.
@Johannes Schaub - litb a un blog, il a trouvé un moyen de rob privé pointeur de membre.
mais je pensais que ce doit être complier de bug ou d'une langue piège.
je peux complie sur gcc4.8, mais pas sur vc8 complier.
donc la conclusion pourrait être :
le propriétaire de construire tous les de porte dérobée.
le voleur a toujours brute et une mauvaise façon de briser dans.
le hacker accidentelle est élégant et de manière automatisée à percer.