Quelle méthode est la meilleure pour implémenter get / set?
Il y a deux methos pour la mise en œuvre get/set.
Méthode 1:
Définir obtenir et de définir séparément.
class my_class
{
//...
};
class main_class
{
public:
my_class get_data() const
{
return m_data;
}
void set_data(my_class value)
{
m_data = value;
}
private:
my_class m_data;
};
Note: Dans cette méthode get est assez rapide: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value
Et une autre méthode (Méthode 2):
Définir deux corps, d'Abord const et un autre non const.
class my_class
{
//...
};
class main_class
{
public:
const my_class& get_data() const
{
return m_data;
}
my_class& get_data() //Works like set.
{
return m_data;
}
private:
my_class m_data;
};
L'utilisation de ces méthodes:
void main()
{
main_class cls;
//For method 1.
my_class data;
data = cls.get_data();
cls.set_data(data);
//For method 2.
const my_class data1;
my_class data2;
data1 = cls.get_data(); //const get invoked.
cls.get_data() = data2; //Like set beacuase non const get invoked.
}
Ma question laquelle de ces méthodes pour la mise en œuvre get/set est mieux?
Connaissez-vous une meilleure méthode?
Modifier:
Pour les réponses qui sont convaincus de la Méthode 1 est la meilleure, qu'en dites-vous dans la situation ci-dessous:
void main()
{
main_class cls;
//For method 1.
cls.get_data().do_something_else(); //Not effictive for cls, because data losts.
//For method 2.
cls.get_data().do_something_else(); //Effictive for cls.
}
source d'informationauteur Amir Saniyan
Vous devez vous connecter pour publier un commentaire.
Vous devriez toujours utiliser une référence pour toutes les classes personnalisées passer juste l'adresse pas de la classe de valeur. Vous devriez aussi éviter de passer à l'arrière d'un non-const de référence pour l'édition. Voir ci-dessous pour mes recommandations.
Je sais que ce ne sera pas une réponse avec C++ puristes et avant que j'ai appris le Python et Ruby, je n'aurais pas abordé la possibilité... mais... Depuis les getter et setter vous avez fourni ne fait pas de vérification de plage ou des calculs spéciaux, pourquoi ne pas rendre le public?
Sûr, vous allez perdre la
const
sur les getter et ne sera pas une garantie de protection, mais vous n'êtes pas garanti que de toute façon parce que vous fournissez un ensemble de fonction qui modifie le membre.Le second est très mauvais comme elle abandonne l'encapsulation: vous pouvez tout aussi bien le domaine public, n'importe qui peut y accéder sans votre objet de savoir à ce sujet. Vous ne pouvez pas effectuer la gamme des chèques ou des mises à jour de statut sur la base des données changé etc.
Le second serait un mauvais choix. La raison d'être des poseurs est d'être en mesure de contrôler la façon dont le membre de la variable est modifiée par l'utilisateur. Si vous venez de donner à l'utilisateur une référence à votre membre, vous perdez tout contrôle.
Si vous êtes un peu gauche avec la première méthode. Ci-dessous sont deux variantes de ce que vous pourriez ou peut ne pas aimer:
Généralement des getters/setters sont définis:
Tout d'abord, je pense que ce n'est pas très efficace
Vous devriez probablement passer par référence
Quant à la méthode que vous devez choisir, de penser de cette façon - En votre deuxième méthode vous renvoyer une référence interne de l'objet et l'utilisateur est absolument libre de faire quelque chose avec elle. Avec la première méthode, vous pouvez contrôler ce que l'utilisateur peut ou ne peut pas faire.
Alors que la norme de getters et settters comme méthode 1 peut fournir "encapsulation", à moins que ces fonctions sont intégrées dans un en-tête, ils sont en ajoutant beaucoup de frais généraux. Par exemple, dans une boucle serrée, même si vous avez utilisé des références plutôt que de passer par valeur (ce qui nécessite alors une coûteuse opération de copie de mémoire), avoir constamment à ajouter environ huit instructions x86 pour chaque appel à un getter/setter pour l'installation jusqu'à l'activation de l'enregistrement sur la pile, ainsi que la fonction du prologue et de l'épilogue est à l'aide du précieux temps CPU, et fait vraiment mal de performance. Puisque vous êtes des accesseurs et des mutateurs ne font pas beaucoup, vous n'avez vraiment pas besoin d'eux.
La méthode 2 est en fait qu'un certain nombre de conteneurs STL faire, comme
std::vector
avec leoperator[]
où vous surchargez la même fonction, mais de définir une constante d'opérations, et l'autre pour les non-constante des opérations ... mais encore une fois, vous êtes en train d'ajouter une surcharge inutile quand vous pourriez accéder publiquement le membre de données (c'est à dire, ce n'est pas comme vous êtes certains sous-jacent pointeurs et les autres à la mémoire de données gérées, membres de nous comme un conteneur STL). Si la fonction que vous êtes en passant qu'il nécessite une référence constante, il ne va pas changer le membre de toute façon, donc il n'y a vraiment aucun besoin de créer une interface comme ceci à moins que vous essayez de faire une interface commune pour accéder à un membre dans une foule de classes. Et si vous faites cela, alors vous devriez regarder dans un pur virtuel de la classe de base pour définir l'interface commune.À mon humble avis la seconde méthode semble très maladroit.