Question

Tous,

Je récemment cette question sur DAL conception. De cela il semblerait que le passage d'une référence à un objet en fonction, avec la fonction alors peuplant cet objet, serait une bonne interface pour une couche de données C ++ Access, par exemple.

  bool DAL::loadCar(int id, Car& car) {} 

Je demande maintenant si vous utilisez une référence à un boost :: shared_ptr serait mieux, par exemple.

  bool DAL::loadCar(int id, boost::shared_ptr<Car> &car)

Toutes les pensées? Est-ce une offre des avantages sur l'autre?

Quelles seraient les conséquences de l'application correcte de const aux deux appels?

Merci d'avance.

Était-ce utile?

La solution

sbi dit: "Cela dépend de la fonction."

Cependant, je pense que l'aspect le plus important de ce qui précède est pas si NULL est autorisée ou non, mais si la fonction stocke un pointeur vers l'objet pour une utilisation ultérieure. Si la fonction ne fait que remplir certaines données alors j'utiliser la référence pour les raisons suivantes:

  • la fonction peut encore être utilisé par les clients qui n'utilisent pas shared_ptr, utilisés pour les objets de la pile, etc.
  • en utilisant la fonction avec shared_ptr est toujours trivial - shared_ptr a déréférencement opérateur qui retourne une référence
  • NULL est le passage impossible
  • moins taper
  • Je n'aime pas utiliser « trucs » quand je n'ai pas

Si la fonction doit stocker le pointeur pour une utilisation ultérieure ou que vous prévoyez la fonction peut changer de telle sorte que nécessitera le stockage d'un pointeur, puis utilisez shared_ptr.

Autres conseils

Cela dépend de ce que la fonction.

En général, une fonction qui prend un pointeur indique que les appelants peuvent appeler cette fonction, même si elles ne sont pas un objet pour passer à - ils peuvent toujours passer NULL. Si cela correspond la spécification de la fonction, puis utiliser un pointeur (smart). En passant référence le comptage des pointeurs intelligents par des références les copier est plutôt une optimisation (et non un prématuré, je dois ajouter), car il évite de plus en plus inutilement et en diminuant le nombre de références, qui peuvent, dans des environnements MT, un succès notable de performance.

Une fonction qui prend une référence non-const comme argument doit être passé un objet valide qu'il pourrait changer. Les appelants ne peuvent pas (légalement) appeler cette fonction à moins qu'ils aient un objet valide et ils ne remettront pas moins qu'ils sont prêts à avoir la fonction changer l'état de l'objet. Si cela correspond mieux à la spécification de la fonction, utilisez une référence.

Si vous devez recevoir un objet valide (ce que vous ne voulez pas l'appelant de passer NULL), puis par tous les moyens, ne pas utiliser boost :: shared_ptr. Votre deuxième exemple passe une référence à un « pointeur intelligent » .... en ignorant les détails, il est un « pointeur vers pointeur vers voiture ». Parce qu'il est fait référence, l'objet shared_ptr ne peut pas être NULL .... mais cela ne signifie qu'il ne peut pas avoir une valeur NULL (à savoir le point à un objet « null »).

Je pourquoi vous pensez comprends pas exactement une référence à un pointeur intelligent serait « meilleur » - ne la fonction de l'appelant utilise pointeur intelligent déjà

?

En ce qui concerne les implications de "const" ... voulez-vous dire quelque chose comme

bool DAL::loadCar(int id, const Car& car) {}

? Si oui, ce serait contre-productif, vous communiquez au compilateur le fait que « voiture » ne change pas (mais on peut supposer que vous voulez que ça change!).

Ou voulez-vous dire pour rendre la fonction « const », quelque chose comme

class DAL{
   bool loadCar(int id, Car& car) const;
}

Dans ce dernier cas, vous comunicate à l'utilisateur compilateur / API que la méthode « loadCar » ne modifie pas l'objet DAL. Il est une bonne idée de le faire si cela est vrai - non seulement il permet des optimisations du compilateur, mais il est généralement une bonne chose à préciser dans la (signature de la fonction) « contrat » que la fonction ne fait aucune modification de DAL, surtout si vous faites cette hypothèse implicite dans votre code (cette façon, vous assurez-vous que cela reste vrai, et que, dans l'avenir personne ne modifiera la fonction « loadCar » d'une manière qui va changer l'objet « DAL »)

Dans le premier cas, vous passez simplement une voiture et « le remplir » avec des informations. Par exemple, vous pouvez créer un « défaut » Car, puis le remplir. Je vois un inconvénient dans ce: il est pas très OO d'avoir deux classes de voitures: un pauvre, par défaut, Car inutile, « vide », et un vraiment rempli Car après cela vient de la fonction. Pour moi, une voiture est une voiture, il devrait donc être une voiture valide (que je peux conduire de l'emplacement A à B, par exemple, celui que je peux accélérer, freiner, démarrer, arrêter). Avant et après votre fonction

Je travaille généralement avec des pointeurs traditionnels, ne stimulerait pas (sans problème, en passant), donc je ne peux pas commenter cette dernière alternative.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top