79 votes

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 cela est hors de la voie, 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 techniques d'accueil)

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).

82voto

dalle Points 9083

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

class safe
{
    int money;

public:
    safe()
     : money(1000000)
    {
    }

    template <typename T>
    void backdoor()
    {
        // Do some stuff.
    }
};

main.cpp:

#include <safe.h>
#include <iostream>

class key;

template <>
void safe::backdoor<key>()
{
    // My specialization.
    money -= 100000;
    std::cout << money << "\n";
}

int main()
{
    safe s;
    s.backdoor<key>();
    s.backdoor<key>();
}

Sortie:

900000
800000

67voto

Je viens d'ajouter une entrée à mon blog qui montre comment il peut être fait. Voici un exemple sur la façon dont vous l'utilisez pour la classe suivante

struct A {
private:
  int member;
};

Il suffit de déclarer un nom de balise et d'instancier un voleur comme le montre l'exemple suivant (mon post montre la mise en œuvre du voleur). Vous pouvez ensuite accéder à ce membre à l'aide d'un pointeur de membre

struct Amem { typedef int type; };
template class rob<Amem, &A::member>;

int main() {
  A a;
  a.*result<Amem>::ptr = 42; // Doh!
}

Mais en réalité, 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.

31voto

ChrisW Points 37322

Ce qui suit est sournois, illégal, compilateur-dépendante, et peut ne pas fonctionner selon différents détails de mise en œuvre.

#define private public
#define class struct

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".


Anothr technique est à accès privé des données sur les membres, par contructing pointeurs à l'aide codée en dur/codée à la main des décalages à partir du début de l'objet.

24voto

Shane MacLaughlin Points 12765

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 ;)

12voto

Rob K Points 3453
class A 
{ 
   int a; 
}
class B
{
   public: 
   int b;
}

union 
{ 
    A a; 
    B b; 
};

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. TC++PL Section C. 8.3 dit "Une classe avec un constructeur, un destructeur, ou opération de copie ne peut pas être le type d'un membre de l'union ... parce que le compilateur ne sais pas quel membre de la détruire."

Donc, nous sommes la gauche avec le meilleur pari est de déclarer la classe B pour correspondre à Une mise en page de l', puis à l'aide de B * b = reinterpret_cast<B*>(&a); comme le "meilleur" "peeping tom" hack pour regarder une classe de soldats.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X