Wohin mit dem Standardparameterwert in C ++?

Wo ist der Standardparameterwert? Nur in der functionsdefinition oder Deklaration oder in beiden Orten?

Standardparameterwerte müssen in der Deklaration erscheinen, da dies das einzige ist, was der Aufrufer sieht.

Bearbeiten: Wie andere darauf hinweisen, können Sie das Argument über die Definition haben, aber ich würde empfehlen, den gesamten Code zu schreiben, als ob das nicht wahr wäre.

Sie können beides tun, aber niemals beides. Normalerweise tun Sie es bei der functionsdeklaration und dann können alle Anrufer diesen Standardwert verwenden. Sie können dies jedoch bei der functionsdefinition tun, und nur diejenigen, die die Definition sehen, können den Standardwert verwenden.

Der nützlichste Platz ist in der Deklaration (.h), so dass alle Benutzer es sehen.

Manche Leute möchten auch die Standardwerte in der Implementierung hinzufügen (als Kommentar):

void foo(int x = 42, int y = 21); void foo(int x /* = 42 */, int y /* = 21 */) { ... } 

Dies bedeutet jedoch eine Duplizierung und fügt die Möglichkeit hinzu, dass der Kommentar nicht mit dem Code übereinstimmt (was ist schlimmer als unkommentierter Code? Code mit irreführenden Kommentaren!).

Obwohl dies ein “alter” Thread ist, möchte ich noch Folgendes hinzufügen:

Ich habe den nächsten Fall erlebt:

  • In der Header-Datei einer class hatte ich
 int SetI2cSlaveAddress( UCHAR addr, bool force ); 
  • In der Quelldatei dieser class hatte ich
 int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force = false ) { ... } 

Wie man sieht, hatte ich den Standardwert des Parameters “force” in der classnquelldatei und nicht in der classnheaderdatei angegeben.

Dann habe ich diese function in einer abgeleiteten class wie folgt verwendet (abgeleitete class hat die Basisklasse auf öffentliche Weise geerbt):

SetI2cSlaveAddress( addr );

Angenommen, es würde den Parameter “force” als “falsch” annehmen.

Allerdings beschwerte sich der Compiler ( in C ++ 11-Modus ) und gab mir den folgenden Compilererrors:

 /home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp: In member function 'void CMax6956Io::Init(unsigned char, unsigned char, unsigned int)': /home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp:26:30: error: no matching function for call to 'CMax6956Io::SetI2cSlaveAddress(unsigned char&)' /home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp:26:30: note: candidate is: In file included from /home/geertvc/mystuff/domoproject/lib/i2cdevs/../../include/i2cdevs/max6956io.h:35:0, from /home/geertvc/mystuff/domoproject/lib/i2cdevs/max6956io.cpp:1: /home/.../mystuff/domoproject/lib/i2cdevs/../../include/i2chal/i2chal.h:65:9: note: int CI2cHal::SetI2cSlaveAddress(unsigned char, bool) /home/.../mystuff/domoproject/lib/i2cdevs/../../include/i2chal/i2chal.h:65:9: note: candidate expects 2 arguments, 1 provided make[2]: *** [lib/i2cdevs/CMakeFiles/i2cdevs.dir/max6956io.cpp.o] Error 1 make[1]: *** [lib/i2cdevs/CMakeFiles/i2cdevs.dir/all] Error 2 make: *** [all] Error 2 

Aber wenn ich den Standardparameter in der Header- Datei der Basisklasse hinzugefügt habe:

int SetI2cSlaveAddress( UCHAR addr, bool force = false );

und entfernte es aus der Quelldatei der Basisklasse:

int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force )

dann war der Compiler glücklich und der gesamte Code funktionierte wie erwartet (ich könnte der function SetI2cSlaveAddress() ) einen oder zwei Parameter geben!

Also, nicht nur für den Benutzer einer class ist es wichtig, den Standardwert eines Parameters in die Header-Datei zu setzen, auch kompilierend und funktional scheint es anscheinend ein Muss zu sein!

Wenn die functionen verfügbar gemacht werden – nicht Mitglied, öffentlich oder geschützt – dann sollte der Aufrufer von ihnen wissen, und die Standardwerte müssen in der Kopfzeile sein.

Wenn die functionen privat und out-of-line sind, ist es sinnvoll, die Standardwerte in die Implementierungsdatei einzufügen, da Änderungen möglich sind, die keine Neukompilierung des Clients auslösen (ein manchmal schwerwiegendes Problem für Low-Level-Bibliotheken, die im Enterprise-Maßstab verwendet werden) Entwicklung). Dennoch ist es potentiell verwirrend, und es gibt einen Dokumentationswert, um die API auf intuitivere Weise in der Kopfzeile zu präsentieren. Wählen Sie also Ihre Kompromisse – obwohl Konsistenz die Hauptsache ist, wenn es keinen zwingenden Grund gibt.

Die Deklaration ist im Allgemeinen die “nützlichste”, aber das hängt davon ab, wie Sie die class verwenden möchten.

beides ist nicht gültig.

Gute Frage … Ich finde, dass Programmierer typischerweise die Deklaration verwenden, um Standardwerte zu deklarieren. Ich wurde auf die eine Art (oder Warnung) oder auf die andere basierend auf dem Compiler festgehalten

 void testFunct(int nVal1, int nVal2=500); void testFunct(int nVal1, int nVal2) { using namespace std; cout < < nVal1 << << nVal2 << endl; } 

Einen weiteren Punkt habe ich niemanden erwähnt erwähnt:

Wenn Sie eine virtuelle Methode haben, kann jede Deklaration einen eigenen Standardwert haben!

Es hängt von der Schnittstelle ab, die Sie anrufen, welcher Wert verwendet wird.

Beispiel für ideone

 struct iface { virtual void test(int a = 0) { std::cout < < a; } }; struct impl : public iface { virtual void test(int a = 5) override { std::cout << a; } }; int main() { impl d; d.test(); iface* a = &d; a->test(); } 

Es druckt 50

Ich rate Ihnen dringend davon ab, es so zu benutzen

Sie können beides tun (entsprechend dem Standard), aber denken Sie daran, wenn Ihr Code die Deklaration ohne Standardargument (en) vor der Definition sieht, die das Standardargument enthält, dann kann es zu einem Kompilierungserrors kommen.

Wenn Sie beispielsweise den Header mit der functionsdeklaration ohne Standardargumentliste einschließen, sucht der Compiler nach diesem Prototyp, da er Ihre Standardargumentwerte nicht kennt und daher der Prototyp nicht übereinstimmt.

Wenn Sie eine function mit einem Standardargument in die Definition einfügen, dann fügen Sie diese Datei hinzu, aber ich werde dies nicht vorschlagen.

Einen weiteren Punkt hinzufügen. functionsdeklarationen mit Standardargument sollten von rechts nach links und von oben nach unten angeordnet werden .

Wenn Sie beispielsweise die Deklarationsreihenfolge in der folgenden functionsdeklaration ändern, gibt der Compiler einen fehlenden Standardparametererrors zurück. Der Compiler erlaubt es Ihnen, die functionsdeklaration mit Standardargument innerhalb des gleichen Bereichs zu trennen, aber in der Reihenfolge von RECHTS nach LINKS (Standardargumente) und von OBEN nach UNTEN (Reihenfolge der functionsdeklaration Standardargument).

 //declaration void function(char const *msg, bool three, bool two, bool one = false); void function(char const *msg, bool three = true, bool two, bool one); // Error void function(char const *msg, bool three, bool two = true, bool one); // OK //void function(char const *msg, bool three = true, bool two, bool one); // OK int main() { function("Using only one Default Argument", false, true); function("Using Two Default Arguments", false); function("Using Three Default Arguments"); return 0; } //definition void function(char const *msg, bool three, bool two, bool one ) { std::cout<