La réponse à la raison pour laquelle nous plaçons des variables de membre privé dans les en-têtes C ++ est que la taille de la classe doit être connue aux points où les instances sont déclarées afin que le compilateur puisse générer du code qui se déplace correctement dans la pile.
Pourquoi devons-nous mettre des membres privés dans les en-têtes?
Mais y a-t-il une raison de déclarer des fonctions privées dans la définition de classe?
L'alternative serait essentiellement l'idiome pimpl mais sans l'indirection superflue.
Cette fonctionnalité linguistique est-elle plus qu'une erreur historique?
Si vous autorisez l'ajout de méthodes à une classe en dehors de sa définition, elles peuvent être ajoutées n'importe où , dans n'importe quel fichier, par n'importe qui.
Cela donnerait immédiatement à tous les codes clients un accès trivial aux membres de données privés et protégés.
Une fois que vous avez terminé la définition de la classe, il n'y a aucun moyen de marquer certains fichiers comme étant spécialement bénis par l'auteur pour l'étendre - il n'y a que des unités de traduction plates. Ainsi, la seule façon raisonnable de dire au compilateur qu'un ensemble particulier de méthodes est officiel, ou béni par l'auteur de la classe, est de les déclarer à l'intérieur de la classe.
Notez que nous avons un accès direct à la mémoire en C ++, ce qui signifie qu'il est généralement trivial de créer un type d'ombre avec la même disposition de mémoire que votre classe, d'ajouter mes propres méthodes (ou simplement de rendre toutes les données publiques), et
reinterpret_cast
. Ou je peux trouver le code de votre fonction privée, ou le démonter. Ou recherchez l'adresse de la fonction dans la table des symboles et appelez ou directement.Ces spécificateurs d'accès n'essaient pas d'empêcher ces attaques, car cela n'est pas possible. Ils indiquent uniquement comment une classe est censée être utilisée.
la source
La réponse acceptée explique cela pour les fonctions privées virtuelles , mais cela ne répond qu'à une facette spécifique de la question, qui est considérablement plus limitée que ce que le PO a demandé. Donc, nous devons reformuler: Pourquoi sommes-nous tenus de déclarer des fonctions privées non virtuelles dans les en-têtes?
Une autre réponse invoque le fait que les classes doivent être déclarées dans un bloc - après quoi elles sont scellées et ne peuvent pas être ajoutées. C'est ce que vous feriez en omettant de déclarer une méthode privée dans l'en-tête puis en essayant de la définir ailleurs. Joli point. Pourquoi certains utilisateurs de la classe devraient-ils pouvoir l'augmenter d'une manière que d'autres utilisateurs ne peuvent pas observer? Les méthodes privées en font partie et n'en sont pas exclues. Mais ensuite vous demandez pourquoi ils sont inclus, et cela semble un peu tautologique. Pourquoi les utilisateurs de classe doivent-ils les connaître? S'ils n'étaient pas visibles, les utilisateurs ne pouvaient pas en ajouter, et hé hop.
J'ai donc voulu apporter une réponse qui, plutôt que de simplement inclure des méthodes privées par défaut, apporte des points spécifiques en faveur de leur visibilité pour les utilisateurs. Une raison mécanique pour les fonctions privées non virtuelles nécessitant une déclaration publique est donnée dans Herb Sutter's GotW # 100 sur l'idiome Pimpl dans le cadre de sa justification. Je ne parlerai pas de Pimpl ici, car je suis sûr que nous le savons tous. Mais voici le morceau pertinent:
Sutter est, bien sûr, une source extrêmement fiable en tant que membre du Comité, donc il connaît "une décision délibérée de conception" quand il en voit une. Et l'idée d'exiger la déclaration publique de méthodes privées comme moyen d'éviter une sémantique altérée ou une accessibilité accidentellement rompue plus tard est probablement la justification la plus convaincante. Heureusement, car le tout semblait plutôt inutile avant maintenant!
la source
Il y a deux raisons à cela.
Tout d'abord, réalisez que le spécificateur d'accès est destiné au compilateur et n'est pas pertinent au moment de l'exécution. L'accès à un membre privé en dehors de la portée est une erreur de compilation .
Concision
Prenons une fonction courte, une ou deux lignes. Il existe pour réduire la réplication de code ailleurs, ce qui a également l'avantage de pouvoir changer la façon dont un algorithme ou quoi que ce soit d'autre fonctionne à un seul endroit au lieu de plusieurs (par exemple changer un algorithme de tri).
Souhaitez-vous plutôt avoir une ou deux lignes rapides dans l'en-tête, ou avoir le prototype de fonction plus une implémentation quelque part? Il est plus facile à trouver dans l'en-tête, et pour les fonctions courtes, il est beaucoup plus détaillé d'avoir une implémentation distincte.
Il y a un autre avantage majeur, qui est ...
Fonctions en ligne
Une fonction privée peut être en ligne, et cela nécessite nécessairement qu'elle soit dans l'en-tête. Considère ceci:
La fonction privée peut être alignée avec la fonction publique. Cela se fait à la discrétion du compilateur, car le
inline
mot clé est techniquement une suggestion , pas une exigence.la source
inline
, il n'y a aucune raison d'y utiliser le mot-clé..cpp
fichier qui est insérée par les fonctions membres qui sont définies en dehors de la définition de classe, mais une telle fonction ne serait pas privée.Une autre raison d'avoir des méthodes privées dans le fichier d'en-tête: Il existe des cas où une méthode en ligne publique ne fait pas beaucoup plus que d'appeler une ou plusieurs méthodes privées. Le fait d'avoir les méthodes privées dans l'en-tête signifie qu'un appel à la méthode publique peut être complètement aligné sur le code réel des méthodes privées, et l'inline ne s'arrête pas avec un appel à la méthode privée. Même à partir d'une unité de compilation différente (et les méthodes publiques généralement appelées à partir de différentes unités de compilation).
Bien sûr, il y a aussi la raison pour laquelle le compilateur ne peut pas détecter les problèmes de résolution de surcharge s'il ne connaît pas toutes les méthodes, y compris les méthodes privées.
la source
C'est pour permettre à ces fonctions d'accéder aux membres privés. Sinon, vous en auriez besoin
friend
dans l'en-tête de toute façon.Si une fonction pouvait accéder aux membres privés de la classe, alors private serait inutile.
la source