Il s'agit d'une question spécifique C. J'essaie de garder tout ce qui est possible à l'intérieur des limites de l'unité de traduction, en exposant seulement quelques fonctions à travers le .h
fichier. Autrement dit, je donne un static
lien vers des objets de niveau fichier.
Maintenant, quelques fonctions doivent être appelées par d'autres modules, mais pas directement. Mon module / fichier / unité de traduction s'abonne aux autres modules, en passant un pointeur sur une fonction. Ensuite, lors d'un événement spécifique, le pointeur est appelé avec quelques arguments.
Je me demande donc comment rendre très évident que ces fonctions sont appelées depuis un endroit obscur.
- Doivent-ils être
static
ouextern
(et les exposer dans le.h
)? - Dois-je inclure un indice dans le nom des fonctions?
- Ou suffit-il de mettre un commentaire "appelé par X"?
c
naming
encapsulation
scope
Vorac
la source
la source
Réponses:
Du point de vue de l'unité de compilation (fichier), la seule chose à laquelle vous devez vous préoccuper est de savoir si la fonction est disponible ou non à l'extérieur. Le rendre disponible signifie qu'il était destiné à être appelé, et vous devez opérer en supposant que ces appels auront lieu. Votre préoccupation avec la fonction elle-même commence à son point d'entrée. La façon dont le contrôle y parvient en premier lieu n'a d'importance que pour le code qui le rend possible.
Étant donné que le lien dans chaque implémentation de CI connu est symbolique, tout ce qui appelle une fonction doit faire référence à son symbole:
Si vous déclarez tort
foo()
d'êtrestatic
, votre programme ne sera pas un lien. Si vous le déclarez nonstatic
, vous avez une fonction exposée qui n'est pas appelée. Les questions sur l'utilisation ou non d'une fonction peuvent être résolues en vidant les tables de symboles de vos fichiers objets ou en les recherchant dans les sources.la source
Définissez «obscur».
Les méthodes doivent être exposées à travers des "interfaces" bien définies et, comme Shivan Dragon l'a déjà suggéré, ces "interfaces" sont vos fichiers .h. Si vous ne donnez pas à un autre programme le "bon" fichier d'en-tête, il ne peut pas appeler la méthode.
static
peut être OK tant que vous n'avez pas de classe [-constitutions similaires] qui contiennent des données d'instance.extern
signifie que vous ne l'implémentez pas du tout; une implémentation est "acquise" ailleurs pendant le processus de liaison.Absolument pas.
Des commentaires comme celui-ci, même s'ils sont bien intentionnés, sont obsolètes au moment où vous avez fini de les écrire.
la source
.h
fichier externe . Il appelle une fonction à partir de là et lui donne un pointeur sur l'une des fonctions du module. Plus tard, le code externe appelle tout ce qui se trouve sur ce pointeur. Ainsi, ma fonction est appelée par quelqu'un qui n'inclut pas mon fichier d'en-tête, j'inclus plutôt le sien.extern
mot clé est redondant » .Si des fonctions de rappel sont définies dans votre module et que l'utilisateur ne fournira jamais l'une des siennes, je pense que vous pouvez utiliser un espace réservé pendant la phase d'initialisation. L'espace réservé est généralement un
enum
qui est ensuite traduit en interne dans la bonnestatic
fonction.la source
Je les ferais toujours
static
(ils ne sont pas destinés à être liés à et appelés par n'importe qui), et marquerais leur objectif comme des rappels fournis à des fonctions externes en leur nom.static
parce que j'essaie de cacher ce que je peux cacher, autant que je peux le cacher.Marquez-les dans leur nom, car a), les commentaires sont obsolètes et b), il devient évident à l'endroit où le rappel est fourni que cette fonction est destinée à être utilisée de cette façon: cela en fait essentiellement un drapeau rouge pour prendre l'adresse d'une fonction qui ne respecte pas la convention de dénomination.
la source
Les modificateurs de portée doivent être utilisés principalement comme informations pour le compilateur, et non comme une forme de documentation "assez proche". L'utilisation de
static
en particulier permet à un compilateur C de rendre la fonction inutilisable de l'extérieur du module, y compris en tant que rappel - pas ce que vous voulez, même si cela peut fonctionner avec votre compilateur actuel.Bien sûr, vous devez ajouter un commentaire au code, car vous pouvez voir que c'est une situation potentiellement déroutante. Tout ce qui est inhabituel ou inattendu a besoin d'un commentaire approprié. Mais, comme indiqué dans d'autres réponses, les commentaires peuvent ne pas être lus ou devenir obsolètes.
Donc, la seule option qui reste est de nommer la fonction pour indiquer qu'il s'agit d'un rappel. La plupart des exemples que j'ai vus utiliser
_callback
ou_cb
comme suffixe, oucb_
comme préfixe. Utilisez le formulaire long si les rappels sont inhabituels dans votre code, le formulaire court s'ils sont courants.la source