C++: pourquoi les fonctions privées doivent-elles être déclarées?
7 réponses
j'ai demandé pourquoi les fonctions privées devaient être déclarées, car elles n'ajoutent rien (ni la taille de l'objet, ni l'entrée vtable) pour que les autres unités de traduction sachent
Si vous pensez à ce sujet, ce qui est similaire à la déclaration de certaines fonctions static
dans un fichier. Il n'est pas visible de l'extérieur, mais il est important que le compilateur lui-même. Le compilateur veut savoir la signature de la fonction avant de l'utiliser. C'est pourquoi vous déclarez des fonctions dans le premier lieu. rappelez-vous que les compilateurs C++ ne sont qu'un passage, ce qui signifie que tout doit être déclaré avant d'être utilisé.1
du point de vue du programmeur, déclarer des fonctions privées n'est toujours pas complètement inutile. Imaginez 2 classes, dont l'une est la friend
de l'autre. Le friendzoned classe2 auraient besoin de savoir à quoi ressemblent les intimes de cette classe, (cette discussion devient bizarre) sinon ils ne peuvent pas utiliser il.
quant à savoir pourquoi exactement C++ a été conçu de cette façon, je dirais d'abord qu'il y a une raison historique: le fait que vous ne pouvez pas trancher une structure en C, a été adopté par C++ donc vous ne pouvez pas trancher une classe (et adopté par d'autres langages ramifiés à partir de C++, aussi). Je suppose aussi que c'est une question de simplicité: imaginez à quel point il serait difficile de concevoir une méthode de compilation dans laquelle vous pouvez partager la classe entre différents fichiers d'en-tête, laisser vos fichiers source le savoir, et empêcher les autres en ajoutant des trucs à ta classe.
Une dernière remarque est que, private
fonctions affecter la taille des vtables. C'est, si elles sont virtual
.
1 en fait pas entièrement. Si vous avez des fonctions inline dans la classe, elles peuvent renvoyer à des fonctions définies plus tard dans la même classe. Mais probablement l'idée a commencé à partir de single pass et cette exception plus tard ajouté à elle.
2C'est inline fonctions de membre en particulier.
vous devez déclarer tous les membres dans la définition de la classe elle-même pour que le compilateur sache quelles fonctions sont permis pour être membres. Sinon, un second programmeur pourrait (accidentellement?) venir et ajouter des membres, faire des erreurs, et violer les garanties de votre objet, provoquant un comportement non défini et/ou des accidents aléatoires.
Il y a une combinaison de préoccupations, mais:
- C++ ne vous permet pas de ré-ouvrir une classe pour y déclarer de nouveaux membres après sa définition initiale.
- C++ ne vous permet pas d'avoir des définitions différentes d'une classe dans différentes unités de traduction qui se combinent pour former un programme.
Donc:
- tout membre privé qui remplit les fonctions de .fichier cpp veut déclarée dans la classe doivent être définies dans le .h fichier, chaque utilisateur de la classe voit trop.
dans le POV de pratique de la compatibilité binaire: comme David dit dans un commentaire, privé virtual
fonctions affectent la taille et la disposition de la vtable de cette classe et de toutes les classes qui l'utilisent comme base. Ainsi, le compilateur a besoin d'en savoir plus sur eux, même lors de la compilation de code qui ne peut pas les appeler.
C++ aurait pu être inventé autrement, pour permettre le .fichier cpp de rouvrir la classe et les ajouter certains types de membres supplémentaires fonctions, avec la mise en œuvre nécessaire pour faire en sorte que cela ne casse pas la compatibilité binaire? La règle de la définition unique pourrait-elle être assouplie afin de permettre des définitions qui diffèrent à certains égards? Par exemple, les fonctions membres statiques et non virtuelle non-fonctions membres statiques.
probablement oui aux deux. Je ne pense pas qu'il y ait d'obstacle technique, bien que L'ODR actuel soit très stricte sur ce qui fait qu'une définition est "différente" (et donc très généreuse à mettre en œuvre dans permettre des incompatibilités binaires entre des définitions très similaires). Je pense que le texte à introduire ce genre d'exception à la règle serait complexe.
en fin de compte, cela pourrait se résumer à "les designers le voulaient de cette façon", ou il se pourrait que quelqu'un ait essayé et ait rencontré un obstacle auquel je n'ai pas pensé.
le niveau d'accès n'affecte pas la visibilité. Les fonctions privées sont visibles par le code externe et peuvent être sélectionnées par résolution de surcharge (ce qui entraînerait une erreur de violation de l'accès):
class A {
void F(int i) {}
public:
void F(unsigned i) {}
};
int main() {
A a;
a.F(1); // error, void A::F(int) is private
}
Imaginez la confusion lorsque cela fonctionne:
class A {
public:
void F(unsigned i) {}
};
int main() {
A a;
a.F(1);
}
// add private F overload to A
void A::F(int i) {}
mais le changer pour le premier code provoque une résolution de surcharge pour sélectionner une fonction différente. Et que dire de l'exemple suivant?
class A {
public:
void F(unsigned i) {}
};
// add private F overload to A
void A::F(int i) {}
int main() {
A a;
a.F(1);
}
ou Voici un autre exemple de ce qui va faux:
// A.h
class A {
public:
void g() { f(1); }
void f(unsigned);
};
// A_private_interface.h
class A;
void A::f(int);
// A.cpp
#include "A_private_interface.h"
#include "A.h"
void A::f(int) {}
void A::f(unsigned) {}
// main.cpp
#include "A.h"
int main() {
A().g();
}
une raison est qu'en C++, Les amis peuvent accéder à vos données privées. Pour les amis, les amis ont à connaître.
Les membres privés d'une classe sont toujours membres de la classe, donc ils doivent être déclarés, car la mise en œuvre d'autres membres publics pourrait dépendre de cette méthode privée. Les déclarer permettra au compilateur de comprendre un appel à cette fonction en tant qu'appel de fonction membre.
Si vous avez une méthode n'est utilisée int .cpp
fichier et ne dépend pas de l'accès direct à d'autres membres privés de la classe, envisager de le déplacer à un espace de nom anonyme. Ensuite, il n'a pas doivent être déclarées dans le fichier d'en-tête.
il y a quelques raisons pour lesquelles les fonctions privées doivent être déclarées.
Première Compilation Des Vérifications D'Erreurs De Temps
le point de modificateurs d'accès est de saisir certaines classes (sans jeu de mots) d'erreurs de programmation au moment de la compilation. Les fonctions privées sont des fonctions qui, si quelqu'un les appelle de l'extérieur de la classe, ce serait un bogue, et vous voulez le savoir le plus tôt possible.
deuxième coulée et L'héritage
extrait du standard c++:
3 [ Note: un membre d'une classe de base privée peut être inaccessible en tant que nom de membre hérité, mais accessible directement. En raison des règles sur les conversions de pointeurs (4.10) et les casts explicites (5.4), une conversion d'un pointeur à une classe dérivée à un pointeur à une classe de base inaccessible pourrait être mal formée si une conversion implicite est utilisée, mais bien formée si un cast explicite est utilisé.
3ème Les amis
les amis s'y montrent les uns aux autres. Une méthode privée peut être appelée par une autre classe qui est un ami.
4ème Générale de l'esprit et la Bonne Conception
a déjà travaillé sur un projet avec 100 autres développeurs. Avoir une norme et un ensemble général de règles aide à maintenir maintenable. déclarer quelque chose de privé a une signification spécifique pour tous les autres membres du groupe.
cela se traduit aussi par de bons principes de conception OO. Ce que pour exposer et ce n'est pas