2009-10-29 6 views
5

HAFTUNGSAUSSCHLUSS: Ich habe nicht C++ für einige Zeit getan ...C/C++ Funktion/Methode Dekoration

Ist es heutzutage üblich C/C++ Funktion/Methode Erklärungen, um dekorieren die Lesbarkeit zu verbessern?

Crude Beispiel:

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

mit dem Makros IN und OUT definiert mit einem leeren Körper (das heißt leichte Dokumentation, wenn Sie in diesem Beispiel). Natürlich verstehe ich, dass dies etwas parallel zu dem "Doc-Kommentarblock" geht, der mit der Methode/Funktion verbunden ist.

Können Sie einige andere Beispiele angeben ... vorausgesetzt, dieses Thema ist nützlich für die Community. Bitte bedenken Sie, dass das obige Beispiel genau das ist, was es ist.

+8

Ich denke, es ist besser, * die INs mit dem 'const' Schlüsselwort * zu markieren. –

+6

Yuck! Making zukünftige Betreuer suchen ein nutzloses Makro, anstatt nur diese Informationen in einen Kommentar zu setzen? Interferenz mit anderen bestehenden Makros riskieren? Nein Danke! – ctd

+0

@Nick D, manchmal möchten Sie nicht-const übergeben durch Wert für IN-Parameter als eine kleine Optimierung 'Typ f (Typ Wert) {Wert.op(); Rückgabewert; } 'Dadurch kann der Compiler nicht nur die Rückgabewertkopie sondern auch die Erstellung von Eingabekopien verhindern, wenn das übergebene Argument ein temporäres Argument ist. –

Antwort

17

Ich würde solche Dekoration nicht schätzen.

Viel besser konst und Referenzen und konstante Referenzen zu verwenden, wie in

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

der Regel durch Wert int übergeben werden und nicht nach, so habe ich AClass und Andere für das Beispiel. Es scheint mir, dass das Hinzufügen von empy IN und OUT ablenken würde.

0

Ich habe das vorher nicht gesehen. Ich wäre der Meinung, es wäre besser, solche Informationen in Kommentare zu schreiben.

1

Ich versuche zu verwenden:

  • Werte für Eingabeparameter oder Referenzen, wenn sie große
  • Referenzen für out-Parameter sind
  • Pointers zu geben, das Eigentum an die aufgerufene Funktion

meisten von der Zeit ist wirklich leicht zu sehen, welche IN oder OUT Parameter sind, natürlich sind Eigennamen in der Deklaration eine gute Dokumentation.

Ich finde diese IN, OUT Addons nervig.

2

nicht in C++, ich habe nicht professionell C-Programmierung gemacht, aber zumindest in C++ die Art des Parameters ist selbsterklärend:

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 

, die zusammen mit in-Code-Tool (doxygen), wo Sie die Dokumentation fügen Sie den Parametern einen Kontext hinzu (welche Werte von der Funktion erwartet oder inakzeptabel sind, wie die Funktion die übergebenen Objekte ändert ...)

Über Zeiger: Wir neigen dazu, unformatierte Zeiger in unseren Methodenschnittstellen zu begrenzen Sie können zwar verwendet werden, aber im Allgemeinen sollten intelligente Zeiger bevorzugt werden, und wiederum stammt die Besitz-Semantik aus der Auswahl e von smart pointer: shared_ptr <> für verdünnte geteilte Verantwortung (oder bei Bedarf), auto_ptr <>/unique_ptr <> für einzelne Besitz (in der Regel als Rückgabewert von Fabriken, Einheimische oder Mitglied Attribute) ...

+0

'T &' kann sowohl "out" als auch "in/out" sein. –

+0

Ja, aber es muss ein komplett konstruiertes Objekt sein, damit es nicht "rein" rauskommt. Ich neige dazu, sie als In/Out-Parameter zu sehen (dies ist nur ich, kein gemeinsamer Grund), unabhängig davon, ob sie intern verarbeitet/gelesen werden. Obwohl akzeptabel, würde ich eine Erklärung für ein Argument benötigen, das durch eine Referenz erhalten wird, deren Wert nicht innerhalb der Funktion in einer Codeüberprüfung verwendet wird. Orte, an denen es akzeptabel ist: eine Funktion, die einen Rohpuffer zurückgibt (Zeiger auf einen Speicherblock), der auch die als Parameter übergebene Größe aktualisiert (nur * nach * hat * wirklich * gerechtfertigt, kein sichereres Konstrukt zu verwenden) oder als Optimierung bei Bedarf –

1

Ich habe gesehen, aber ich glaube nicht, ich würde sagen, es ist „üblich.“

Der Win32-API (C nicht C++) verwendet etwas ähnliches:

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 
    ); 

Im Fall des Visual C++ 2005 und später Compiler, diese Karte tatsächlich Erklärungen wie __$allowed_on_parameter und werden zum Zeitpunkt der Kompilierung geprüft.

7

Windows-Header tatsächlich tun genau dies. Eine vollständige Liste der verwendeten Anmerkungen finden Sie unter Header Annotations. Zum Beispiel“

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

Für diese Funktion ist ein optionaler hModule Eingabeparameter ist lpFilename ein Ausgabeparameter, die maximal nSize Zeichenelemente speichern und welche enthält (der Rückgabewert der Funktion) +1 Zeichenelemente Bei der Rückgabe ist nSize ein

+1

+1. Dieser Blog-Eintrag hat Hintergrund und weitere Beispiele: http://blogs.msdn.com/michael_howard/archive/2006/05/19/602077.aspx –

+6

Aber das sind keine leeren Makros - am Ende erweitern sie auf SAL-Attribute wie '[SA_Pre (...)]' und '[SA_Post (...)]', die vom Compiler tatsächlich behandelt werden. –

5

Zu Dokumentationszwecken genügt ein gut geschriebener Kommentarblock, so dass diese keinen Zweck erfüllen, außerdem haben einige Dokumentationskommentare eine spezielle Syntax für genau solche eine Sache, zum Beispiel gegeben Doxygen, könnten Sie schreiben:

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

... aber was ist für Dinge außerhalb der Dokumentation Sorge? – jldupont

+1

Was meinst du? Sie können und sollten alle Methoden dokumentieren, nicht nur die in der öffentlichen API. Zum Zweck der Dokumentationsgenerierung gibt es normalerweise einen Weg, um anzugeben, welche Methoden "für den privaten Gebrauch" sind, so dass sie nicht in öffentliche Dokumente gelangen - z. "intern" in Doxygen. –

+0

Wenn Sie sich die Dokumente nicht ansehen, sehen Sie sich den Quellcode an. Wenn es nicht zumindest ziemlich offensichtlich ist, müssen Sie Elemente in der Quelle umgestalten und/oder umbenennen, anstatt sie zu dekorieren. –

4

Ich denke, das ist eine schlechte Idee. Zumal jeder mitkommen kann und die Makros IN/OUT definiert und dich in großen Schwierigkeiten stecken lässt.

Wenn Sie es Kommentare wollen dokumentieren, setzen dort wirklich.

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

warum auch eine Out verwenden, wenn ein Wert Rückkehr wird gut funktionieren.
Auch würde ich es vorziehen Pass von ref zu verwenden und const ref meine Absichten anzuzeigen. Außerdem macht der Compiler jetzt relativ gute Optimierungen für die Absicht, wenn Ihr Code const korrekt ist.

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

guter Punkt ... danke! – jldupont

+0

@Martin: bis zu dem "char *" Kommentar, den du gemacht hast, hatte ich meinen Disclaimer oben auf der Frage ;-) – jldupont

+1

/* +1 */(im Gegensatz zu PLUSONE) –

1

Das einzige, was noch schlimmer dann dies wurde in einem C-Programm geschrieben vor langer Zeit gesehen von Pascal dev:


#define begin { 
#define end } 

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

Ich sah Verwendung von Präfixen i_, o_, IO_ zusätzlich zu den Informationen in Parametertypen :

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