2010-05-16 10 views

Antwort

153

Wenn Sie die Erklärung in einer Header-Datei setzen, und die Definition in einer separaten Datei .cpp und #include der Header aus einer anderen .cpp Datei, werden Sie in der Lage sein, den Unterschied zu sehen.

Insbesondere nehme:

lib.h

int Add(int a, int b); 

lib.cpp

int Add(int a, int b = 3) { 
    ... 
} 

test.cpp

#include "lib.h" 

int main() { 
    Add(4); 
} 

Die Zusammenstellung von test.cpp nicht sehen, die defa Ult Parameter Deklaration, und wird mit einem Fehler fehlschlagen.

Aus diesem Grunde wird die Standard-Parameterdefinition in der Regel in der Funktion Erklärung angegeben:

lib.h

int Add(int a, int b = 3); 
+0

Dann wird 'b' mehrfach definiert, einmal für jede Kompilierungseinheit, die' lib.h' enthält, ist das richtig? – httpinterpret

+0

@httpinterpret: in einem Sinne ja, der Standardwert von 'b' ist einmal definiert für * jede * '.cpp' Datei, die den Header enthält. Aber das ist in Ordnung, weil Sie nur eine Deklaration der 'Add'-Funktion haben. –

+0

@httpinterpret Der Compiler fügt den nicht angegebenen Parameter beim Generieren des Aufrufercodes durch den Standardparameter hinzu. Deshalb MUSS der Standardwert im Funktionsprototyp sein und nicht in der Funktionsimplementierung. Der Parameter ist nicht definiert im Sinne der Variablendefinition, da der Prototyp keine Variablen definiert. – harper

4

Standard Argumente müssen mit dem ersten Auftreten der Funktion Namen- angegeben werden typischerweise im Funktionsprototyp. Wenn der Funktionsprototyp weggelassen wird, weil die Funktionsdefinition auch als Prototyp dient, sollten die Standardargumente im Funktionskopf angegeben werden.

3

Der erste Weg wäre dem zweiten vorzuziehen.

Dies liegt daran, dass die Header-Datei zeigt, dass der Parameter optional ist und was sein Standardwert sein wird. Darüber hinaus wird sichergestellt, dass der Standardwert derselbe ist, unabhängig von der Implementierung der entsprechenden CPP-Datei.

In der zweiten Möglichkeit gibt es keine Garantie für einen Standardwert für den zweiten Parameter. Der Standardwert kann sich ändern, je nachdem, wie die entsprechende CPP-Datei implementiert ist.

36

In C++ die auf Standardargumente hinsichtlich ihrer Lage in Parameterliste gestellten Anforderungen sind wie folgt: hat Standardargument für einen bestimmten Parameter

  1. nicht mehr als einmal angegeben werden. Es mehr als einmal zu spezifizieren (sogar mit dem gleichen Standardwert) ist illegal.

  2. Parameter mit Standardargumenten müssen eine zusammenhängende Gruppe am Ende der Parameterliste bilden.

Jetzt hält, dass im Auge, in C++ Sie dürfen den Satz von Parametern „wachsen“, die Standardargumente aus einer Erklärung der Funktion zum nächsten haben, solange die oben genannten Anforderungen kontinuierlich erfüllt sind .

Zum Beispiel können Sie eine Funktion ohne Standardargumente

void foo(int a, int b); 

Um erklären, diese Funktion nach einer solchen Erklärung rufen werden Sie beide Argumente explizit angeben.

Später (weiter unten) in derselben Übersetzungseinheit, können Sie es wieder neu erklären, aber diesmal mit einem Standardargument

void foo(int a, int b = 5); 

und von diesem Punkt an Sie es mit nur einem explizit nennen Streit.

Weiter unten können Sie es erneut erklären noch einmal ein

void foo(int a = 1, int b); 

und von diesem Punkt mehr Standardargument Zugabe auf Sie es ohne explizite Argumente aufrufen können.

Das vollständige Beispiel aussehen könnte, wie in Ihrer Frage

void foo(int a, int b); 

int main() 
{ 
    foo(2, 3); 

    void foo(int a, int b = 5); // redeclare 
    foo(8); // OK, calls `foo(8, 5)` 

    void foo(int a = 1, int b); // redeclare again 
    foo(); // OK, calls `foo(1, 5)` 
} 

void foo(int a, int b) 
{ 
    // ... 
} 

Wie für den Code folgt, sind beide Varianten perfekt gültig, aber sie bedeuten verschiedene Dinge. Die erste Variante deklariert sofort ein Standardargument für den zweiten Parameter. Die zweite Variante deklariert zunächst Ihre Funktion ohne Standardargumente und fügt dann eine für den zweiten Parameter hinzu.

Der Nettoeffekt beider Deklarationen (d. H. Die Art und Weise, wie der Code nach der zweiten Deklaration aussieht) ist genau gleich: Die Funktion hat das Standardargument für ihren zweiten Parameter. Wenn es Ihnen jedoch gelingt, Code zwischen der ersten und der zweiten Deklaration zu komprimieren, verhalten sich diese beiden Varianten unterschiedlich. In der zweiten Variante hat die Funktion keine Standardargumente zwischen den Deklarationen, daher müssen Sie beide Argumente explizit angeben.

+0

Ich glaube nicht, dass Ihr Code definierte void foo (int a = 1, int b) funktionieren würde. Sie müssen alle optionalen Parameter nach einem optionalen Parameter haben. Es ist ein Syntaxfehler (zumindest mit g ++ 4.5.3 auf meinem System). – Nilesh

+0

@Nilesh: Wie ich oben (und das ist der ganze Punkt dieses Beispiels) explizit für 'void foo (int a = 1, int b)' gesagt habe, muss es * nach * 'void foo (int a , int b = 5) '. Ja, es wird funktionieren. Und nein, es ist kein Syntaxfehler. g ++ 4.5.3 kompiliert es einwandfrei. – AnT

+0

Okay, so nimmt die Funktion den Wert von b aus der vorherigen Deklaration. Das Ding jetzt holen. Danke :-) – Nilesh