1.
int Add (int a, int b = 3);
int Add (int a, int b)
{
}
2.
int Add (int a, int b);
int Add (int a, int b = 3)
{
}
Obie działają; jaki jest standardowy sposób i dlaczego ?
1.
int Add (int a, int b = 3);
int Add (int a, int b)
{
}
2.
int Add (int a, int b);
int Add (int a, int b = 3)
{
}
Obie działają; jaki jest standardowy sposób i dlaczego ?
Odpowiedzi:
Jeśli umieścisz deklarację w pliku nagłówkowym, a definicję w osobnym .cpp
pliku, a #include
nagłówek z innego .cpp
pliku, zobaczysz różnicę.
W szczególności przypuśćmy:
int Add(int a, int b);
int Add(int a, int b = 3) {
...
}
#include "lib.h"
int main() {
Add(4);
}
Kompilacja test.cpp
nie zobaczy domyślnej deklaracji parametru i zakończy się niepowodzeniem z błędem.
Z tego powodu domyślna definicja parametru jest zwykle podawana w deklaracji funkcji :
int Add(int a, int b = 3);
b
jest definiowana raz dla każdego .cpp
pliku zawierającego nagłówek. Ale to w porządku, ponieważ masz tylko jedną deklarację Add
funkcji.
W C ++ wymagania stawiane argumentom domyślnym w zakresie ich umiejscowienia na liście parametrów są następujące:
Domyślny argument dla danego parametru należy podać nie więcej niż raz. Podanie go więcej niż raz (nawet z tą samą wartością domyślną) jest niedozwolone.
Parametry z domyślnymi argumentami muszą tworzyć ciągłą grupę na końcu listy parametrów.
Mając to na uwadze, w C ++ możesz „powiększać” zestaw parametrów, które mają domyślne argumenty z jednej deklaracji funkcji do następnej, o ile powyższe wymagania są stale spełniane.
Na przykład możesz zadeklarować funkcję bez domyślnych argumentów
void foo(int a, int b);
Aby wywołać tę funkcję po takiej deklaracji, musisz jawnie określić oba argumenty.
Później (niżej) w tej samej jednostce tłumaczeniowej możesz ponownie zadeklarować ją ponownie, ale tym razem z jednym domyślnym argumentem
void foo(int a, int b = 5);
i od tego momentu możesz to wywołać za pomocą tylko jednego wyraźnego argumentu.
Dalej możesz zadeklarować go ponownie, dodając jeszcze jeden domyślny argument
void foo(int a = 1, int b);
i od tego momentu możesz go wywoływać bez wyraźnych argumentów.
Pełny przykład może wyglądać następująco
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)
{
// ...
}
Jeśli chodzi o kod w twoim pytaniu, oba warianty są całkowicie prawidłowe, ale mają różne znaczenie. Pierwszy wariant od razu deklaruje domyślny argument dla drugiego parametru. Drugi wariant początkowo deklaruje twoją funkcję bez domyślnych argumentów, a następnie dodaje jeden dla drugiego parametru.
Efekt netto obu deklaracji (tj. Sposób, w jaki jest to postrzegane przez kod następujący po drugiej deklaracji) jest dokładnie taki sam: funkcja ma domyślny argument dla drugiego parametru. Jeśli jednak uda Ci się wcisnąć jakiś kod między pierwszą a drugą deklaracją, te dwa warianty będą się zachowywać inaczej. W drugim wariancie funkcja nie ma domyślnych argumentów między deklaracjami, więc będziesz musiał jawnie określić oba argumenty.
void foo(int a = 1, int b)
aby zadziałało, musi zostać zadeklarowane później void foo(int a, int b = 5)
. Tak, to zadziała. I nie, to nie jest błąd składniowy. g ++ 4.5.3 skompiluje to doskonale.
int foo(int)
. Stwierdzam, że mogę pisać int foo(int=5)
ponownie, pomijając nazwy parametrów. Jak dotąd nikt o tym nie wspomniał.
Pierwsza metoda byłaby lepsza od drugiej.
Dzieje się tak, ponieważ plik nagłówkowy pokaże, że parametr jest opcjonalny i jaka będzie jego wartość domyślna. Dodatkowo zapewni to, że wartość domyślna będzie taka sama, niezależnie od implementacji odpowiedniego pliku .cpp.
W drugim przypadku nie ma gwarancji wartości domyślnej drugiego parametru. Wartość domyślna może się zmienić w zależności od tego, jak zaimplementowano odpowiedni plik .cpp.
b
zostanie zdefiniowany wiele razy, raz dla każdej jednostki kompilacji, która zawieralib.h
, czy to prawda?