4 votes

C++ : Autoriser l'accès aux membres protégés de la classe et non aux membres privés

Je sais que vous pouvez le faire avec l'héritage, mais vous êtes censé utiliser l'héritage pour des circonstances autres que "est un". Je sais également qu'il existe des amis, mais ils permettent également l'accès aux membres privés.

Y a-t-il un moyen de faire cela (autoriser l'accès aux membres protégés de la classe et non aux membres privés) ?

Pour reformuler la question, j'ai la classe 1 et la classe 2. Je veux que la classe 2 ait accès aux membres protégés et publics de la classe 1, mais pas à ses membres privés. Comment dois-je m'y prendre ?

5voto

Oli Charlesworth Points 148744

Ce n'est pas élégant, mais cela pourrait vous convenir :

class B;

class A {
protected:
    int x;
private:
    int y;
};

class A_wrapper : public A {
    friend B;
};

class B {
public:
    A_wrapper a;
    int foo() {
        a.x;   // Ok
        a.y;   // Compiler error!
    }
};

2voto

Matthieu M. Points 101624

Il y a longtemps, sur ce même site, j'ai présenté un schéma utilisant une Key . L'idée est que la classe principale documente les parties de l'interface qui sont accessibles publiquement et celles qui nécessitent une clé, puis l'amitié pour la clé est accordée à ceux qui en ont besoin.

class Key { friend class Stranger; Key() {} ~Key() {} };

class Item {
public:
    void everyone();

    void restricted(Key);
private:
};

Maintenant, seulement Stranger peut utiliser le restricted comme cela est démontré ici :

class Stranger {
public:
    void test(Item& i) {
        Key k;
        i.restricted(k);
    }

    Key key() { return Key(); }

    Key _key;
};

class Other {
    void test(Item& i) {
        Stranger s;
        i.restricted(s.key()); // error: ‘Key::~Key()’ is private
                               // error: within this context
    }

    void test2(Item& i) {
        Stranger s;
        i.restricted(s._key); // error: ‘Key::~Key()’ is private
                              // error: within this context
                              // error:   initializing argument 1 of ‘void Item::restricted(Key)’
    }
};

Il s'agit d'un système très simple qui permet une approche beaucoup plus fine que l'amitié totale.

1voto

justin Points 72871

Oli a fourni une solution plus proche (+1), mais vous pourriez aussi l'aborder en utilisant un ami sélectif :

#include <iostream>

class t_thing;

class t_elsewhere {
public:
    void print(const t_thing& thing);
};

class t_thing {
public:
    class t_selective_friend {
        static int Prot(const t_thing& thing) {
            return thing.prot;
        }

        friend class t_elsewhere;
    };
public:
    int publ;
protected:
    int prot;
protected:
    int priv;
};

void t_elsewhere::print(const t_thing& thing) {
    std::cout << t_thing::t_selective_friend::Prot(thing) << std::endl;
}

int main() {
    t_thing thing;

    thing.publ; /* << ok */
    thing.prot; /* << error */
    thing.priv; /* << error */
    t_elsewhere().print(thing); /* << ok */
    return 0;
}

Parfois, cette verbosité/contrôle a du bon

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