2009-10-29 3 views
5

DISCLAIMER: Je ne l'ai pas fait C++ pour un certain temps ...C/C++ fonction/décoration méthode

Est-il courant de nos jours pour décorer la fonction C/C++/déclarations de méthode afin d'améliorer la lisibilité?

brut Exemple:

void some_function(IN int param1, OUT char **param2);

avec les macros IN OUT et définies avec un vide corps (à savoir la documentation légère si vous voulez dans cet exemple). Bien sûr, je comprends que cela va un peu en parallèle avec le "bloc de commentaires doc" associé à la méthode/fonction.

Pourriez-vous fournir d'autres exemples ... en supposant que ce sujet soit utile à la communauté. S'il vous plaît gardez à l'esprit que l'exemple ci-dessus est juste ce qu'il est.

+8

Je pense qu'il est préférable de * marquer * les IN avec le mot clé 'const'. –

+6

Yuck! Faire en sorte que les futurs responsables recherchent une macro inutile au lieu de simplement ajouter cette information dans un commentaire? Risque d'interférence avec d'autres macros existantes? Non merci! – ctd

+0

@Nick D, vous voulez parfois utiliser une valeur de passe non constante pour les paramètres IN comme une petite optimisation 'type f (type value) {value.op(); valeur de retour; } 'Cela permet au compilateur d'élider non seulement la copie de la valeur de retour mais aussi la création de copies d'entrée si l'argument transmis est temporaire. –

Répondre

17

Je n'apprécierais pas une telle décoration.

beaucoup mieux d'utiliser const et des références et des références constantes, comme dans

void some_function(AClass const &param1, AnotherClass &param2) 

Habituellement int sont passés par valeur et non par référence, donc j'utilisé AClass et AnotherClass pour l'exemple. Il me semble que l'ajout d'empy IN et OUT serait distrayant.

0

Je n'avais jamais vu ça auparavant. Je pense qu'il serait préférable de mettre de telles informations dans les commentaires.

1

J'essaie d'utiliser:

  • Les valeurs des paramètres d'entrée ou des références si elles sont grandes
  • Références pour les paramètres sur
  • Pointeurs pour donner la propriété à la fonction appelée

La plupart du temps est vraiment facile à voir qui sont des paramètres IN ou OUT, bien sûr les noms propres dans la déclaration sont une bonne documentation.

Je trouve ces addons IN, OUT agaçants.

2

pas en C++, je n'ai pas fait la programmation C par des professionnels, mais au moins en C++ du type des paramètres est explicite:

void f(std::string const &); // input parameter 
void f(std::string);   // input parameter again (by value) 
void f(std::string&);  // in/out parameter 
std::string f();    // output 

qui, avec des outils documentation en code (doxygen) où vous ajouter du contexte aux paramètres (quelles valeurs sont attendues ou inacceptables par la fonction, comment la fonction change les objets passés ...

A propos des pointeurs: Nous avons tendance à limiter les pointeurs bruts dans nos interfaces de méthode. , ils peuvent être utilisés, mais en général, les pointeurs intelligents devraient être préférés.Puis encore, la sémantique de propriété vient du choix e du pointeur intelligent: shared_ptr <> pour la responsabilité partagée diluée (ou si nécessaire), auto_ptr <>/unique_ptr>> pour une propriété unique (généralement comme valeur de retour d'usines, d'habitants ou d'attributs de membre) ...

+0

'T &' peut être à la fois "out" et "in/out", cependant. –

+0

Oui, mais il doit être un objet entièrement construit, il est donc pas « purement » sur. J'ai tendance à les voir (ce n'est que moi, pas un terrain d'entente) comme des paramètres d'entrée/sortie, qu'ils soient traités ou lus à l'intérieur. Bien qu'acceptable, j'aurais besoin d'une explication pour un argument reçu par référence dont la valeur n'est pas utilisée à l'intérieur de la fonction dans une revue de code. Les endroits où il est acceptable: une fonction renvoyant un tampon brut (pointeur vers un bloc de mémoire) qui met à jour également la taille comme paramètre (seulement * après * avoir * vraiment * justifié de ne pas utiliser plus sûr construction) ou l'optimisation si nécessaire –

1

J'ai vu cela, mais je ne pense pas que je dirais que c'est "commun".

L'API Win32 (C non C++) utilise quelque chose de similaire:

WINADVAPI 
BOOL 
WINAPI 
CreateProcessWithLogonW(
    __in  LPCWSTR lpUsername, 
    __in_opt LPCWSTR lpDomain, 
    __in  LPCWSTR lpPassword, 
    __in  DWORD dwLogonFlags, 
    __in_opt LPCWSTR lpApplicationName, 
    __inout_opt LPWSTR lpCommandLine, 
    __in  DWORD dwCreationFlags, 
    __in_opt LPVOID lpEnvironment, 
    __in_opt LPCWSTR lpCurrentDirectory, 
    __in  LPSTARTUPINFOW lpStartupInfo, 
    __out  LPPROCESS_INFORMATION lpProcessInformation 
    ); 

Dans le cas de Visual C++ 2005 et plus tard compilateurs, ces carte fait des déclarations comme __$allowed_on_parameter et sont vérifiées au moment de la compilation.

7

Les en-têtes Windows font exactement cela. Voir Header Annotations pour la liste complète des annotations utilisées. Par exemple »

DWORD 
WINAPI 
GetModuleFileName(
    __in_opt HMODULE hModule, 
    __out_ecount_part(nSize, return + 1) LPTSTR lpFilename, 
    __in DWORD nSize 
    ); 

Pour cette fonction, hModule est un paramètre d'entrée en option, lpFilename est un paramètre de sortie qui stockent un maximum de nSize éléments caractéristiques et qui contient (la valeur de retour de la fonction) +1 éléments caractéristiques

+1

+1. Cette entrée de blog a fond et d'autres exemples: http://blogs.msdn.com/michael_howard/archive/2006/05/19/602077.aspx –

+6

Mais ce ne sont pas des macros vides - à la fin, ils étendent aux attributs SAL tels que '[SA_Pre (...)]' et '[SA_Post (...)]', qui sont en fait gérés par le compilateur. –

5

À des fins de documentation, un bloc de commentaire bien écrit est suffisant, de sorte que ceux-ci ne servent à rien. une chose, par exemple, donné Doxygen, vous pouvez écrire:

/** 
* @param[in] param1 ... 
* @param[out] param2 ... 
**/ 
void some_function(int param1, char **param2); 
+0

... mais qu'en est-il des choses en dehors de la documentation? – jldupont

+1

Que voulez-vous dire? Vous pouvez et devez documenter toutes les méthodes, pas seulement celles de l'API publique. Aux fins de la génération de la documentation, il est généralement possible de déterminer quelles méthodes sont «à usage privé», afin qu'elles ne soient pas utilisées dans les documents publics - p. '\ internal' dans Doxygen. –

+0

Si vous ne regardez pas les documents, vous regardez le code source. Si ce n'est pas assez évident, vous devez refactoriser et/ou renommer les éléments de la source au lieu de les décorer. –

4

Je pense que c'est une mauvaise idée. Surtout que n'importe qui peut venir et définir les macros IN/OUT et vous laisser dans un tas de problèmes.

Si vous voulez vraiment le documenter, mettez des commentaires là-dedans.

void some_function(/* IN */ int param1, /* OUT */ char **param2); 

Également pourquoi utiliser une sortie lorsqu'une valeur de retour fonctionnera correctement.
Aussi je préférerais utiliser pass par ref et const ref pour indiquer mes intentions. Aussi le compilateur fait maintenant une optimisation relativement bonne pour l'intention quand votre code est const correct.

void some_function(/* IN */ int const& param1, /* OUT */ char*& param2); 
// OK for int const& is kind of silly but other types may be usefull. 
+0

bon point ... merci! – jldupont

+0

@ Martin: jusqu'à la « char * » comment vous faites, j'ai eu mon avertissement en haut de la question ;-) – jldupont

+1

/* 1 */(par opposition à Plusone) –

1

La seule chose pire que cela a été vu il y a longtemps dans un programme C écrit par Pascal dev:


#define begin { 
#define end } 

int main(int argc, char* argv[]) 
begin 
    ... 
end 
0

j'ai vu l'utilisation des préfixes i_, o_, io_ en plus des informations sur les types de paramètres :

void some_function(int i_param1, char** o_param2, int& io_param3); 
Questions connexes