Funzione / metodo C / C ++ decorazione
-
22-07-2019 - |
Domanda
DISCLAIMER: Non faccio C ++ da un po 'di tempo ...
Oggigiorno è comune decorare le dichiarazioni di metodi / funzioni C / C ++ per migliorare la leggibilità?
Esempio di greggio:
void some_function(IN int param1, OUT char **param2);
con le macro IN e OUT definite con un corpo vuoto (vale a dire una documentazione leggera se si intende in questo esempio). Ovviamente capisco che questo va in qualche modo parallelamente al & Quot; blocco dei commenti doc & Quot; associato al metodo / funzione.
Potresti fornire altri esempi ... supponendo che questo argomento sia utile alla comunità. Per favore tieni presente che l'esempio sopra è proprio quello che è.
Soluzione
Non apprezzerei tale decorazione.
Molto meglio usare const, riferimenti e riferimenti costanti, come in
void some_function(AClass const ¶m1, AnotherClass ¶m2)
Di solito int viene passato per valore e non per riferimento, quindi ho usato AClass e AnotherClass per l'esempio. Mi sembra che aggiungere empy IN e OUT sia fonte di distrazione.
Altri suggerimenti
Le intestazioni di Windows fanno esattamente questo. Vedere Annotazioni intestazione per l'elenco completo di annotazioni utilizzate. Ad esempio & Quot;
DWORD
WINAPI
GetModuleFileName(
__in_opt HMODULE hModule,
__out_ecount_part(nSize, return + 1) LPTSTR lpFilename,
__in DWORD nSize
);
Per questa funzione, hModule
è un parametro di input facoltativo, lpFilename
è un parametro di output che memorizza un massimo di nSize
elementi di carattere e che conterrà (il valore di ritorno della funzione) +1 elementi di carattere in al ritorno, e <=> è un parametro di input.
Ai fini della documentazione, è sufficiente un blocco di commenti ben scritto, quindi non servono a nessuno scopo. Inoltre, alcuni parser di commenti di documentazione hanno una sintassi speciale proprio per una cosa del genere; ad esempio, dato Doxygen, potresti scrivere:
/**
* @param[in] param1 ...
* @param[out] param2 ...
**/
void some_function(int param1, char **param2);
Penso che questa sia una cattiva idea. Soprattutto dal momento che chiunque può venire e definire le macro IN / OUT e lasciarti in grande difficoltà.
Se vuoi davvero documentarlo inserisci commenti.
void some_function(/* IN */ int param1, /* OUT */ char **param2);
Anche perché usare un out quando un valore di ritorno funzionerà bene.
Inoltre preferirei usare pass by ref e const ref per indicare le mie intenzioni. Anche il compilatore ora fa relativamente bene l'ottimizzazione dell'intento quando il tuo codice è corretto.
void some_function(/* IN */ int const& param1, /* OUT */ char*& param2);
// OK for int const& is kind of silly but other types may be usefull.
Non in C ++, non ho fatto C in modo professionale ma almeno in C ++ il tipo di parametri è autoesplicativo:
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
Che insieme agli strumenti di documentazione in-code (doxygen) in cui aggiungi un po 'di contesto ai parametri (quali valori sono previsti o inaccettabili dalla funzione, come la funzione cambia gli oggetti passati ...
Informazioni sui puntatori: tendiamo a limitare i puntatori non elaborati nelle nostre interfacce dei metodi. Se necessario, possono essere utilizzati, ma in generale dovrebbero essere preferiti i puntatori intelligenti. Inoltre, la semantica della proprietà viene dalla scelta del puntatore intelligente: shared_ptr & Lt; & Gt; per la responsabilità condivisa diluita (o quando necessario), auto_ptr < > / unique_ptr < > per singola proprietà (di solito come valore di ritorno da fabbriche, locali o attributi dei membri) ...
Provo a usare:
- Valori per parametri di input o riferimenti se sono grandi
- Riferimenti per i parametri out
- Puntatori per assegnare la proprietà alla funzione chiamata
Il più delle volte è davvero facile vedere quali sono i parametri IN o OUT, ovviamente i nomi propri nella dichiarazione sono una buona documentazione.
Trovo fastidiosi quei componenti aggiuntivi IN, OUT.
L'ho visto, ma non credo che direi che è " comune. "
L'API Win32 (C non C ++) usa qualcosa di simile:
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
);
Nel caso di Visual C ++ 2005 e compilatori successivi, questi in realtà corrispondono a dichiarazioni come __$allowed_on_parameter
e vengono controllati al momento della compilazione.
L'unica cosa peggiore di questa è stata vista molto tempo fa in un programma C scritto da Pascal dev:
#define begin {
#define end }
int main( int argc, char* argv[] )
begin
...
end
Non l'ho mai visto prima. Penso che sarebbe meglio inserire informazioni come questa nei commenti.
Ho visto l'utilizzo dei prefissi i_, o_, io_ oltre alle informazioni nei tipi di parametro:
void some_function(int i_param1, char** o_param2, int& io_param3);