Mais je ne sais pas si je devrais aller pour des méthodes statiques, une en-tête, une classe ou autre chose?
Quelle serait la meilleure pratique? Mais, je ne veux pas avoir une instance d'une classe d'utilité. P>
Je veux ajouter des fonctions telles que: p>
5 Réponses :
Ne les mettez pas dans une classe; Il suffit de les faire des fonctions non membres à la portée des espaces de noms. P>
Il n'y a aucune règle qui dit que chaque fonction doit être une fonction membre de certaines catégories. P>
@James: Oh, un espace de noms. Peut-être pas mauvais ... Pouvez-vous donner un petit exemple de code?
Certains magasins préfèrent les cours sur les espaces de noms parce que c'est plus «Java comme». soupir i>
@Martijn: Je vous recommande d'obtenir l'un des ouvrages d'introduction répertoriés dans Le définitif C ++ Guide de livres et liste . Effectivement, le code peut être tout comme vous le montrerez dans votre question, et si vous souhaitez que vous souhaitiez ou que vous souhaitez, vous pouvez placer les fonctions dans un espace de noms.
@FLYFISH Toute personne qui tente de transformer C ++ en Java regarde un océan de douleur.
Je connais la syntaxe, mais qu'en est-il des fichiers? Dois-je créer un fichier séparé pour cela? Avec quel nom?
@Martijn: C'est à vous de décider. Je recommanderais de séparer les utilitaires et les algorithmes en différents en-têtes en fonction de leur cas d'utilisation et de leur fonctionnalité générale.
Vous pouvez créer un fichier par fonction ou un fichier par famille de fonctions, etc. ... C'est une question de gestion des dépendances et c'est à vous de définir la granularité que vous souhaitez souhaiter. C'est un compromis puisque une plus grande granularité signifie un nombre plus élevé de fichiers, mais moins de dépendances.
Si vous créez un fichier par fonction, préparez-vous à être détesté par des générations à venir.
@James: L'en-tête de l'espace de noms doit-il avoir des gardes d'en-tête?
@James: L'utilisation d'un espace de noms a un gros inconvénient si vous avez besoin de fonctions d'assistance qui ne devraient être accessibles que par les fonctions utilitaires, mais pas directement non par l'utilisateur. Dans une classe, vous faites des personnes simplement privées ...
@rstevens: Dans ce cas, les fonctions d'assistance peuvent être placées dans un espace de noms "détaillé". C'est, par exemple, quelle que soient la plupart des bibliothèques de boost.
@rstevens: Ce n'est qu'un problème si l'utilisateur est soit (a) malveillant, ou (b) muet. Cela dit, qu'est-ce que cela importe? Les fonctions non membres ne sont pas des fonctions membres, elles ne peuvent donc pas manipuler de manière inappropriée de l'état privé d'aucun objet; Si quelqu'un veut les appeler comme utilitaires, il ne devrait y avoir aucun problème.
@James: Il peut y avoir des fonctions utilitaires internes qui modifient une instance de classe donnée sous forme de paramètre de manière erronée si les autres paramètres ne sont pas définis correctement. Vous pouvez donc empêcher l'utilisateur de les appeler directement. C'est la même raison pour laquelle les méthodes privées utilisées uniquement pour les paramètres soumis.
Il n'y a probablement aucune raison d'avoir une classe pour envelopper ces fonctions s'ils n'appartiennent pas logiquement à une classe. Dans ce cas, vous pouvez simplement les avoir des fonctions libres. Il pourrait être approprié de les contenir dans un espace de noms pour éviter les collisions de noms. P>
Si vous souhaitez fournir un regroupement logique Stringer des classes, il n'y a pas de préjudice réel à leur avoir des fonctions de membre statique d'une classe - mais je ne vois aucune raison pour que vous auriez des fonctions telles que mapRgB () < / code> et
Copystring () code> doit être membre de la même classe. P>
Un facteur est de savoir s'il faut même les mettre dans une classe ou simplement les mettre en tant que nomembers dans un espace de noms (en Java, vous devez utiliser une classe, mais C ++ offre des espaces de noms). P>
Si vous en faites un membre de la classe, la décision la plus importante que vous devez faire sur chaque fonction est de savoir si elle nécessiterait ou devrait affecter n'importe quel état qui n'est pas reçu ou transmis via ses paramètres et sa valeur de retour. Si ce n'est pas le cas, il convient de faire: Un argument d'utilisation d'une classe au lieu d'un espace de noms est si votre classe de services publics peut avoir besoin d'invoquer des méthodes supplémentaires pour sa mise en œuvre (par exemple, dans un cas de récursivité, de calcul complexes, etc.). Vous pouvez alors faire votre méthode en termes de conception de l'interface de fonction, tenez compte du nombre d'arguments. S'il y a trop d'arguments entrants (surtout s'ils sont de types similaires et certains sont liés), vous voudrez peut-être envisager d'utiliser des types supplémentaires au lieu de passer plusieurs arguments. Par exemple, au lieu de statique code>, car vous n'utiliserez pas la "Cet argument caché". P>
statique public code> et tout ce qu'il est implémenté sur
statique privé code>. Cela fait de nombreuses années depuis que j'ai utilisé C ++, mais je ne pense pas que vous puissiez "masquer" des fonctions non membres dans un espace de noms (quelqu'un me corrige si je me trompe). p>
Calculatvolume (int x, int y, int z) code>, vous pouvez faire quelque chose comme
CalculateVolume (Point3D) code>. De même, dans votre cas, utilisez une classe RVB. Cela peut sembler stupide, mais il peut enregistrer certaines erreurs ennuyeuses (par exemple, si vous avez des fonctions qui prennent des INT et des RGBS) et une heure (si vous devez transmettre les valeurs à d'autres fonctions). Vous pouvez créer une méthode d'usine statique pour faciliter la création de ces types lors de la transmission des arguments.
Par exemple:
DOSOMODHCOLOR (RGB.Create (20,30,40)) CODE> P>
Si une fonction non membre est implémentée dans un fichier .cpp. CPPP, toutes les fonctions dont elles ont besoin, mais qui ne doivent pas être exposées peuvent être placées dans un espace de noms non nommé dans ce fichier .CPP (ou fabriqué statique). Il est plus difficile si vous avez des modèles de fonction, car leur mise en œuvre doit être dans le fichier d'en-tête lui-même, mais cela est généralement résolu en ayant un espace de noms «détail» dans lequel se passe la fonctionnalité non publique. C'est l'approche qu'une grande quantité de boost prend.
Si vous voulez simplement collecter des fonctions ensemble, mais ne pas créer une instance du groupe, vous devriez probablement penser à les mettre dans un espace de noms plutôt qu'à une classe du tout. P>
J'essaierais d'utiliser des espaces de noms significatifs, cependant, mettez MapprGB et de la dépolation, il est très peu de sens. Si vous avez vraiment besoin de la fois et que vous n'avez vraiment pas d'autres fonctions qui traitent de la cartographie des chaînes ou de la RVB, les mettre dans un espace de noms «utilité» peut avoir un sens, mais si vous utilisez celles-ci, Il semble que vous ayez une autre chaîne "Stuff" et d'autres choses "de couleur", et que vous pourriez probablement bénéficier d'un espace de noms pour chacun. P>
J'ai généralement un .a (.Lib sur Windows) appelé "util" qui est lié à. Cependant, généralement une classe "util" est une mauvaise nouvelle et introduit une dépendance qui brise la conception standard orientée objet. Maintenant, si vous essayez de retirer une classe pour réutiliser dans un autre projet, vous avez des milliers de dépendances cachées sur votre bibliothèque UTIL. Fondamentalement, c'est utile, mais faites de votre mieux pour éviter de mettre les choses là-bas. P>
CopyString () semble suspect - que fera-t-il?
@Neil: Copier une chaîne sur le tas, de sorte qu'il ne sort pas de la portée ...
NE PAS, en aucune circonstance, c'est une fuite de mémoire presque garantie. Utilisez STD :: String.
@Neil: Mais STD :: String sera également hors de portée, lorsqu'il est créé sur la pile?
@Martijn: Lorsque vous retournez une chaîne par valeur, elle est copiée au retour. Vous devriez obtenir l'un des ouvrages d'introduction répertoriés sur le Guide de livres C ++ définitif et la liste < / a>. Ces livres contiennent de très bonnes explications sur le fonctionnement de base de C ++.
J'ai deuxième James ici - de vos questions, vous semblez avoir vraiment besoin d'un bon livre sur la programmation et la conception de C ++. Vous ne pouvez pas apprendre C ++ de poser des questions sur SO.
@Neil @james: En effet! Maintenant, je me souviens, il est passé de valeur. Le constructeur de copie sera appelé.
Sur la plupart des implémentations, il n'est même pas copié beaucoup lorsque "Copier" une chaîne STD :: String par valeur, car elle utilise une optimisation en faisant référence à l'ancienne valeur et en créant une copie uniquement si la chaîne doit être modifiée.