107 votes

Pourquoi puis-je accéder à des variables privées dans le constructeur de la copie ?

J'ai appris que je ne peux jamais accéder à une variable privée, seulement avec une fonction get dans la classe. Mais alors pourquoi puis-je y accéder dans le constructeur de la copie ?

Exemple :

Field::Field(const Field& f)
{
  pFirst = new T[f.capacity()];

  pLast = pFirst + (f.pLast - f.pFirst);
  pEnd  = pFirst + (f.pEnd - f.pFirst);
  std::copy(f.pFirst, f.pLast, pFirst);
}

Ma déclaration :

private:
  T *pFirst,*pLast,*pEnd;

130voto

aioobe Points 158466

Les modificateurs d'accès fonctionnent sur niveau du cours et non sur niveau de l'objet .

Autrement dit, deux objets de la même classe peuvent accéder aux membres privés de l'autre.

46voto

Tony D Points 43962

À mon avis, les réponses existantes n'expliquent pas bien le "pourquoi" de cette situation - elles se concentrent trop sur la réitération des comportements valides. "Les modificateurs d'accès fonctionnent au niveau de la classe, et non au niveau de l'objet". - oui, mais pourquoi ?

Le concept général ici est que c'est le(s) programmeur(s) qui conçoit, écrit et maintient une classe qui est (sont) censé(s) comprendre l'encapsulation OO souhaitée et être habilité(s) à coordonner sa mise en œuvre. Donc, si vous écrivez class X vous n'encodez pas seulement la façon dont un individu X x peut être utilisé par le code qui y a accès, mais aussi comment :

  • les classes dérivées sont en mesure d'interagir avec elle (par le biais de fonctions virtuelles pures et/ou d'un accès protégé), et
  • distinct X objets coopérer pour fournir les comportements voulus tout en respectant les post-conditions et les invariants de votre conception.

Il n'y a pas que le constructeur de copie - un grand nombre d'opérations peuvent impliquer deux ou plusieurs instances de votre classe : si vous comparez, ajoutez/multipliez/divisez, construisez par copie, clonez, assignez, etc., il est fréquent que vous deviez avoir accès à des données privées et/ou protégées dans l'autre objet, ou que vous vouliez permettre une implémentation de fonction plus simple, plus rapide ou généralement meilleure.

Plus précisément, ces opérations peuvent vouloir profiter d'un accès privilégié pour faire des choses comme.. :

  • (constructeurs de copie) utilisent un membre privé de l'objet "rhs" (right hand side) dans une liste d'initialisation, de sorte qu'une variable membre est elle-même construite par copie au lieu d'être construite par défaut (si c'est légal) puis assignée (encore une fois, si c'est légal)
  • partager les ressources - poignées de fichiers, segments de mémoire partagée, shared_ptr aux données de référence, etc.
  • s'approprier les choses, par exemple auto_ptr<> "déplace" la propriété vers l'objet en construction
  • copier les membres privés du "cache", de l'étalonnage ou de l'état nécessaires à la construction du nouvel objet dans un état d'utilisation optimale sans devoir les régénérer à partir de zéro.
  • copier/accéder à des informations de diagnostic/trace conservées dans l'objet copié, qui ne sont pas autrement accessibles par les API publiques mais qui pourraient être utilisées par un objet d'exception ou une journalisation ultérieure (par exemple, quelque chose sur le moment/les circonstances où l'instance "originale" non copiée a été construite)
  • effectuer une copie plus efficace de certaines données : par exemple, les objets peuvent avoir par exemple une unordered_map mais n'exposent publiquement que begin() y end() itérateurs - avec un accès direct aux size() vous pourriez reserve pour une copie plus rapide ; pire encore, s'ils ne font qu'exposer at() y insert() et sinon throw ....
  • recopier les références aux objets parents/coordination/gestion qui peuvent être inconnus ou en écriture seule pour le code client.

37voto

Alexander Rafferty Points 3853

Vous pouvez accéder aux membres privés d'une classe à partir de cette dernière, même à ceux d'une autre instance.

12voto

Ali Zaib Points 41

Pour comprendre la réponse, j'aimerais vous rappeler quelques notions.

  1. Quel que soit le nombre d'objets que vous créez, il n'y a qu'une seule copie d'une fonction en mémoire pour cette classe. Cela signifie que les fonctions ne sont créées qu'une seule fois. En revanche, les variables sont distinctes pour chaque instance de la classe.
  2. this est transmis à chaque fonction lorsqu'elle est appelée.

Maintenant, c'est à cause de la this Avec un pointeur, la fonction est capable de localiser les variables de cette instance particulière, peu importe qu'elles soient privées ou publiques, elles peuvent être accédées à l'intérieur de cette fonction. Maintenant, si nous passons un pointeur à un autre objet de la même classe, en utilisant ce second pointeur, nous serons en mesure d'accéder aux membres privés.

J'espère que cela répond à votre question.

7voto

Bojan Komazec Points 4248

Le constructeur de copie est une fonction membre de la classe et, en tant que tel, il a accès aux membres de la classe, même ceux qui sont déclarés "privés".

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