Conventions pour les méthodes accesseurs (getters et setters) en C++
Plusieurs questions à propos des méthodes accesseur en C++ ont été posées sur, mais aucun n'a été en mesure de satisfaire ma curiosité sur la question.
J'essaie d'éviter les accesseurs chaque fois que possible, parce que, comme Stroustrup célèbres et d'autres programmeurs, je considère une classe avec beaucoup d'entre eux un signe de mauvais OO. En C++, je peux, dans la plupart des cas, ajouter plus de responsabilité à une classe ou à l'utilisation de l'ami de mot-clé pour les éviter. Pourtant, dans certains cas, vous avez vraiment besoin de l'accès à certains membres de la classe.
Il y a plusieurs possibilités:
1. Ne pas utiliser des accesseurs à tous les
Nous pouvons juste faire respectifs des variables de membre du public. C'est un no-go en Java, mais semble être OK avec le C++ de la communauté. Cependant, je suis un peu inquiet à propos de cas ont été explicite d'une copie ou lecture seule (const) une référence à un objet doit être renvoyé, c'est que exagérées?
2. L'utilisation de Java de style méthodes get/set
Je ne sais pas si c'est du Java, mais je veux dire ceci:
int getAmount(); //Returns the amount
void setAmount(int amount); //Sets the amount
3. Utiliser objective-C-style méthodes get/set
C'est un peu bizarre, mais apparemment de plus en plus commun:
int amount(); //Returns the amount
void amount(int amount); //Sets the amount
Dans l'ordre pour que cela fonctionne, vous devrez trouver un autre nom pour votre membre de la variable. Certaines personnes, ajouter un trait de soulignement, d'autres à mettre "m_". Je n'aime pas non plus.
Style utilisez-vous et pourquoi?
- Petit-seulement les structures de côté, ce qui vous a donné l'impression de variables de membre publiques serait ok en C++? Ses généralement pas ainsi.
- Oui, c'est un no-go en C++. Mais si vous avez travaillé avec MFC, vous pourriez obtenir de l'hypothèse qu'il serait OK.
- Plus récemment discuté en tant que [set/get méthodes en C++ ](stackoverflow.com/questions/3632533), que j'ai trouvé avec les moteurs de recherche "c++ getter setter". Voir aussi [Getter et setter, des pointeurs ou des références et de la bonne syntaxe à utiliser en c++? ](stackoverflow.com/questions/1596432), C++ getters/setters style de codage et probablement d'autres.
- Voir cet article (PDF) pourquoi getters/setters sont tout simplement faux.
- Fritzsche: je pense que je l'ai vu dans la STL et boost, mais je ne suis pas sûr en fait. @dmckee: Oui, il y a un tas de messages sur ce sujet et ils sont tous intéressants, mais aucun ne répond à mes questions spécifiques.
- Je ne vois pas comment vous question d'ajouter quoi que ce soit. Il reste juste poser une question stylistique qui a été aldready demandé à de multiples reprises ici, je suis à peu près sûr. Vous pourriez peut-être le point où votre question en fait d'innover? Vous ne semblent même pas au point que vous pourriez en fait besoin d'un get et pas un ensemble de méthode ou toute autre variante.
- Vous auriez à me forcer à écrire publique getters et setters en C++; ils sont clairement inutiles sur leur visage, à moins qu'ils ont un effet secondaire.
Vous devez vous connecter pour publier un commentaire.
De mon point de vue que de s'asseoir avec 4 millions de lignes de code C++ (et ce n'est qu'un projet) à partir d'un entretien de point de vue, je dirais:
C'est ok de ne pas utiliser des getters/setters si les membres sont immuables (c'est à dire
const
) ou de simples sans dépendances (comme une classe point avec les membres X et Y).Si un membre du
private
que c'est aussi ok pour ignorer des getters/setters. Je compte également des membres de l'interne pimpl-classes commeprivate
si l' .rpc unité est petite.Si un membre du
public
ouprotected
(protected
est tout aussi mauvais quepublic
) et nonconst
, non simple ou a des dépendances ensuite utiliser des getters/setters.Comme un gars de l'entretien, ma principale raison de vouloir avoir des getters/setters est parce que j'ai alors un endroit pour mettre des points d'arrêt /enregistrement /quelque chose d'autre.
Je préfère le style de la variante 2. comme c'est plus consultable (un élément clé dans l'écriture de code maintenable).
Je n'ai jamais utiliser ce style. Parce qu'il peut limiter l'avenir de la conception des classes et explicite geters ou setters sont tout aussi efficace avec un bon compilateurs.
Bien sûr, dans la réalité inline explicite getters ou poseurs de créer autant de sous-jacents à la dépendance de l'implémentation de la classe. Ils ont juste réduire la dépendance sémantique. Vous avez encore de tout recompiler si vous les modifiez.
C'est mon style par défaut lorsque j'utilise des méthodes accesseurs.
Ce style semble trop "intelligent" pour moi. Je ne l'utiliser qu'en de rares occasions, mais seulement dans les cas où j'ai vraiment envie de l'accesseur pour se sentir autant que possible, comme une variable.
Je crois qu'il y a un cas pour de simples sacs de variables avec, éventuellement, un constructeur pour s'assurer qu'ils sont tous initialisés à quelque chose de sain d'esprit. Quand je fais cela, j'ai tout simplement faire un
struct
et laisser tous les publics.2) est le meilleur de l'OMI, car il rend vos intentions les plus claires.
set_amount(10)
est plus significative queamount(10)
, et comme un effet secondaire de nice, permet à un membre nomméamount
.Variables publiques est généralement une mauvaise idée, car il n'y a pas d'encapsulation. Supposons que vous avez besoin de mettre à jour un cache ou d'actualisation d'une fenêtre lorsqu'une variable est mise à jour? Tant pis si vos variables sont publiques. Si vous avez une méthode de jeu, vous pouvez l'ajouter là.
getId()
appel: par de la farce que de la logique dans un getter/setter vous ne respectez pas le contrat de la méthode d'accesseur. Vous n'aurez pas à briser le code client de la compilation de cette façon, mais vous ne serez certainement casser son moteur d'exécution de l'opération, ce qui est encore pire. Parce que personne dans un état sain d'esprit va supposer que votre getter peut, dire, faire de l'allocation de mémoire parfois, ou votre poseur pourra écrire à un système de fichiers. Dans tous ces scénarios, vous devez refonte pour les nouvelles exigences.C'est un bon style, si nous voulons nous représenter
pure
de données.Je n'aime pas ça 🙂 parce que
get_/set_
est vraiment inutile quand on peut surcharger en C++.STL utilise ce style, comme
std::streamString::str
etstd::ios_base::flags
, sauf quand il devrait être évité! quand? Lorsque la méthode des conflits de nom avec un autre type de nom, puisget_/set_
style est utilisé, commestd::string::get_allocator
en raison destd::allocator
.En général, j'ai l'impression que ce n'est pas une bonne idée d'avoir trop de getters et setters être utilisé par un trop grand nombre d'entités dans le système. C'est juste une indication d'une mauvaise conception ou de mauvaise encapsulation.
Après avoir dit que, si une telle conception doit être refait, et le code source est disponible, je préfère utiliser le Design pattern Visiteur. La raison en est:
Idée de base est:
Je ne voudrais pas exclure les accesseurs de l'utilisation. Peut pour certains POD structures, mais je les considère comme une bonne chose (certains accesseurs pourrait avoir d'autres logiques, trop).
Il n'a pas vraiment matière à la convention d'affectation de noms, si vous êtes cohérent dans votre code. Si vous utilisez plusieurs bibliothèques tierces, ils peuvent utiliser différentes conventions de nommage de toute façon. Donc, c'est une question de goût.
J'ai vu l'idéalisation des classes plutôt que les types intégraux à consulter des données significatives.
Quelque chose comme ci-dessous n'est généralement pas une bonne utilisation de C++ propriétés:
Pourquoi? Parce que le résultat de p.la masse*p.l'accélération est un float et non pas de la force comme prévu.
La définition de classes de désigner un but (même si c'est une valeur, comme montant mentionné précédemment), plus de sens, et de nous permettre de faire quelque chose comme:
Vous pouvez accéder à la valeur du montant implicitement par l'opérateur int. En outre:
Getter/Setter utilisation:
C'est une approche différente, ne signifie pas qu'il est bon ou mauvais, mais différent.
Laissez-moi vous raconter une autre possibilité, qui semble le plus conscise.
Besoin de lire & modifier
Il suffit de déclarer la variable public:
Avez juste besoin de lire
L'inconvénient de cette approche est que vous avez besoin de changer tout le code appelant (ajouter des parenthèses, c'est-à) lorsque vous voulez modifier le modèle de l'accès.
Une autre possibilité pourrait être :
Je ne suis pas sûr, je le recommande, mais il a l'avantage de l'insolite notation peut s'abstenir aux utilisateurs de modifier les données.
Parfois, il est peut-être juste le bon choix à faire:
Une autre possibilité encore une fois, utiliser la notation fonctionnelle pour modifier l'objet.
De cette façon dangereuse/fonction d'édition peut être retiré dans un namespace avec sa propre documentation. Celui-ci semble venir naturellement à la programmation générique.
operator =
au lieu d'une référence à un membre de données.operator=
dans le premier cas, c'est évidemment une bonne chose à faire au minimum. Je voudrais utiliser la deuxième, dans certains cas, si je veux assurer la fonctionnalité d'édition transverse à la hiérarchie de classe, et quand il fait sens de séparer clairement cette fonctionnalité dans la classe. C'est probablement une mauvaise idée pour un simple poseur de bien.