Getter et setter, pointeurs ou références, et bonne syntaxe à utiliser en c ++?
Je voudrais savoir une bonne syntaxe de C++ getters et setters.
private:
YourClass *pMember;
le setter est facile, je suppose:
void Member(YourClass *value){
this->pMember = value; //forget about deleting etc
}
et de la lecture?
dois-je utiliser des références ou des pointeurs const?
exemple:
YourClass &Member(){
return *this->pMember;
}
ou
YourClass *Member() const{
return this->member;
}
quoi la différence entre eux?
Merci,
Joe
EDIT:
désolé, je vais modifier ma question... je sais que sur les références et les pointeurs, je posais des questions à propos des références et pointeurs const, comme les méthodes de lecture, quelle serait la différence entre les deux dans mon code, comme dans le futur, ce que doit je m'attendre à perdre si je pars d'une manière ou d'une autre...
donc je suppose que je vais utiliser const pointeurs au lieu de références
const pointeurs pouvez pas supprimer ou sertie, droit?
source d'informationauteur Jonathan
Vous devez vous connecter pour publier un commentaire.
Comme une loi générale:
Donc, si le setter devrait peut être appelée avec la valeur NULL, utilisez un pointeur en paramètre. Sinon, utiliser une référence.
Si c'est valable pour appeler de la lecture d'un objet contenant un pointeur NULL, il doit retourner un pointeur. Si un tel cas est illégale d'un invariant, la valeur de retour doit être une référence. De la lecture puis doit lancer une exception, si le membre de la variable est NULL.
La meilleure chose est de fournir un vrai OO interface pour le client qui cache implementaton de détails. Les accesseurs et Mutateurs ne sont pas OO.
Votre code ressemble beaucoup comme si vous êtes habitué à une autre langue -- en C++ à l'aide de
this->x
(pour un exemple) est relativement inhabituel. Lorsque le code est bien écrit, est d'utiliser un accesseur ou mutateur.Si je suis assez rare sur ce point particulier, je vais aller sur enregistrer (encore une fois) que de dire que le fait de forcer code client à utiliser un accesseur ou mutateur est une mauvaise idée. Si vous honnêtement à une situation où il fait sens pour le code client de manipuler une valeur de votre objet, puis le code client doit utiliser attribution normale de lecture et/ou écriture de la valeur.
Quand/si vous avez besoin de contrôler ce que la valeur est affectée, la surcharge d'opérateur permet d'en prendre le contrôle sans forcer laid get/set de syntaxe sur le code du client. Plus précisément, ce que vous voulez, c'est une classe proxy (ou modèle de classe). Juste pour un exemple, l'une des situations les plus courantes où les gens veulent obtenir/fonctions de jeu est quelque chose comme un certain nombre qui est censé être limité à certains plage. Le
setXXX
vérifie la nouvelle valeur pour être dans la gamme, et lagetXXX
retourne la valeur.Si vous voulez, un (assez) simple modèle peut faire le travail beaucoup plus proprement:
Cela aussi rend le code beaucoup plus proche de l'auto de documenter, par exemple, lorsque vous déclarez un objet comme:
bounded<int>(1, 1024);
il est immédiatement évident que l'intention est un entier dans la plage de 1 à 1024. La seule partie que quelqu'un pourrait trouver la question est de savoir si 1 et/ou 1024 est inclus dans la gamme. Ce qui est considérablement différent de la définition d'un int dans la classe, et s'attendant à tout le monde qui regarde la classe pour réaliser qu'ils sont censés utiliser le setXXX à appliquer (à ce point inconnu) de l'ensemble des bornes sur les valeurs qui peuvent être affectées.Lorsque vous incorporez un de ces dans une classe, vous en faites une variable publique, et la gamme est toujours appliquée. Dans le code du client, il n'y a pas de réel argument de plus à la syntaxe -- vous êtes juste de l'affectation à une variable publique, comme vous le feriez pour tout autre -- avec le petit détail qui tente de déterminer une valeur hors de la plage de lever une exception. En théorie, la classe devrait probablement prendre un modèle politique-paramètre pour spécifier exactement ce qu'il fait dans ce cas, mais je n'ai jamais eu une vraie raison de s'embêter avec ça.
Comme d'autres l'ont dit, l'utilisation des pointeurs si la valeur null est une possibilité.
Dans la plupart des cas, je préfère utiliser des références si possible. Personnellement, dans mon code, j'aime utiliser la distinction entre les pointeurs et les références de signal de la propriété. Je pense d'appels avec des références comme "prêt" d'un objet à une autre fonction ou de la classe. La classe d'origine, qui est passé ou retourné la référence encore en est le propriétaire, et est responsable de sa création, d'entretien et de nettoyage. Quand mon code passe un non-const pointeur, d'autre part, cela signifie généralement qu'il y a une sorte de transfert ou le partage de la propriété en cours, avec toutes les responsabilités que cela implique.
(Et oui, j'ai l'habitude d'utiliser des pointeurs intelligents. Ceux qui sont comparables à des références dans mon esprit. Je parle de niveau inférieur que le code ici.)
La référence est un alias de la chose(il est la chose*). Un pointeur est l'adresse de la chose. Si il y a une chance que ce qui est fait pour ne pas être là, alors vous ne voulez probablement pas à revenir références. Références dire l'appelant "je vais vous donner un alias qui existent quand je reviendrai à vous". En fait, il n'y a vraiment aucun moyen de vérifier la référence pour voir si ce qui est sous-jacent est valide.
Avec le pointeur, sémantiquement, tu sous-entends que l'appelant pouvez vérifier pour voir si le Membre existe avant de l'utiliser. Ussually cela est fait avec un NULL vérifier.
En fin de compte il n'y a pas de "bonne" réponse. Il dépend de la classe du contrat et si l'appelant va/doit/veut vérifier si "Membre" est toujours autour de.
La réponse courte est des pointeurs pour les choses qui peuvent être pointés ailleurs et références pour "détrôné" alias.
+1 sur remet en question l'utilisation de setters et getters. Si vous devez utiliser et d'avoir la possibilité de les valeurs null envisager d'utiliser boost::shared_ptr. De cette façon, la propriété est fait pour vous.
En plus des autres réponses, si vous choisissez les références pour la lecture ne pas l'écrire comme dans votre exemple:
Votre getter permet en effet, ainsi qu'il en
instance->Member() = YourClass();
et contournant ainsi votre setter. Cela pourrait ne pas être autorisée si YourClass est noncopyable, mais il est encore une autre chose à avoir à l'esprit. Un autre inconvénient est que la lecture n'est pas const.Au lieu de cela, écrire votre getter comme ceci:
Jonathan, quel compilateur que vous utilisez? Il y a une grande chance que
shared_ptr
déjà est fournie avec le compilateur TR1 mise en œuvre.