Les autres réponses expliquent le raisonnement derrière la prévention de votre objet B
d'accéder à les parties de A
protégées dans votre exemple, même si B
« est-a » A
. Bien sûr, la meilleure façon de résoudre ce problème est de rendre les parties de A you want access to
public` ou ont des méthodes d'accès accessibles au public.
Cependant, vous pouvez décider que est inappropriée (ou vous pourriez ne pas avoir le contrôle sur la définition de A
). Voici quelques suggestions pour vous permettre de contourner le problème, en augmentant l'ordre de subvertir le contrôle d'accès de A
. Notez que toutes ces solutions de contournement supposent que est constructible par copie.
Dans le premier cas, vous utilisez simplement le constructeur de copie pour A
de mettre en place un état initial pour cette partie de l'objet B
, puis le corriger après:
class B1 : public A
{
public:
B1() : A(), z(0) {}
B1(const A& item) : A(item), z(1) {
// fix up the A sub-object that was copy constructed
// not quite the way we wanted
x = y;
y = 0;
}
private:
int z;
};
Je trouve que très confus et probablement très sujette aux erreurs (en supposant que nous voulons que le sous-objet à être différent dans l'objet B
A
que l'objet A
étant transmis au constructeur - une situation inhabituelle, mais il est ce qui a été donné dans le problème).Cependant, le fait que cela peut être fait donne une justification pour les exemples les plus subversives qui suivent ...
L'exemple suivant crée un objet B
temporaire qui a une copie exacte de l'objet que nous voulons A
accès. On peut alors utiliser l'objet B
temporaire pour accéder aux éléments qui ont été protégés:
class B2 : public A
{
public:
B2() : A(), z(0) {}
B2(const A& item) : A(), z(1) {
// create a special-use B2 object that can get to the
// parts of the A object we want access to
B2 tmp(item, internal_use_only);
x = tmp.y; // OK since tmp is of type B
}
private:
int z;
// create a type that only B2 can use as a
// 'marker' to call a special constructor
// whose only purpose in life is to create
// a B object with an exact copy of another
// A sub-object in it
enum internal_use {
internal_use_only
};
B2(const A& item, internal_use marker) : A(item), z(0) {};
};
Je trouve cette solution à être un peu moins confus que le premier, mais il est encore confus (à mon avis). Avoir une version bastarde de l'objet B juste pour accéder aux parties de l'objet A que nous voulons est étrange.
Nous pouvons faire quelque chose à ce sujet en créant un proxy spécial pour A
objets qui donne l'accès que nous voulons. Notez que c'est la solution de contournement la plus subversive car c'est quelque chose que n'importe quelle classe peut faire pour accéder aux parties protégées de A
, même si elles ne sont pas des sous-classes de A
elles-mêmes. Dans le cas de la classe B
, il y a une certaine légitimité pour obtenir les pièces protégées de A
objets, car B
est-un A
, et comme nous l'avons déjà vu il y a des solutions de contournement qui nous permettent d'obtenir un accès qui utilisent les droits seulement qui class B
déjà a, donc je considère que c'est une version plus propre de ces solutions de contournement dans le cas de class B
.
class B3 : public A
{
public:
B3() : A(), z(0) {}
B3(const A& item) : A(), z(1) {
// a special proxy for A objects that lets us
// get to the parts of A we're interested in
A_proxy tmp(item);
x = tmp.get_y();
}
private:
int z;
class A_proxy : public A
{
public:
A_proxy(const A& other) : A(other) {};
int get_x() {return x;};
int get_y() {return y;};
};
};
peut-être, vous avez oublié 'virtual'? –
Pavel: oops, ouais, j'ai ajouté le mot-clé 'virtual' ... ça ne change pas vraiment mon point, cependant :) –