기능 매개 변수의 기본값


130

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

}

두 작품 모두; 표준 방법은 무엇 이며 왜 그렇 습니까?

답변:


203

선언을 헤더 파일에 넣고 정의를 별도의 .cpp파일 에 넣고 다른 파일 의 헤더를 넣으면 #include차이 .cpp를 볼 수 있습니다.

구체적으로 다음과 같이 가정하십시오.

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

컴파일 test.cpp하면 기본 매개 변수 선언이 표시되지 않으며 오류와 함께 실패합니다.

이러한 이유로 기본 매개 변수 정의는 일반적으로 함수 선언에 지정됩니다 .

lib.h

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

그런 다음 b포함 된 각 컴파일 단위에 대해 여러 번 정의됩니다 lib.h. 맞습니까?
httpinterpret

@httpinterpret : 어떤 의미에서 그렇습니다. 기본값 은 헤더를 포함하는 파일 b대해 한 번 정의 .cpp됩니다. 그러나 Add함수 에 대한 선언은 하나뿐이므로 괜찮습니다 .
Greg Hewgill

1
@httpinterpret 호출자 코드가 생성 될 때 컴파일러는 기본 매개 변수로 지정되지 않은 매개 변수를 추가합니다. 이것이 기본값이 함수 구현이 아닌 함수 프로토 타입에 있어야하는 이유입니다. 프로토 타입은 변수를 정의하지 않으므로 변수 정의의 의미로 매개 변수가 정의 되지 않습니다.
harper

1
이 구문은 빠른 구문 분석 (코드를보고 "이러한 이유로"까지 진행되지 않음)으로 인해 사용자가 의도 한 것과 반대되는 내용을 이해했기 때문에 편집 할 수 있습니다.
Gabriel Devillers

44

C ++에서 매개 변수 목록에서의 위치와 관련하여 기본 인수에 부과 된 요구 사항은 다음과 같습니다.

  1. 주어진 매개 변수의 기본 인수는 한 번만 지정해야합니다. 동일한 기본값으로 두 번 이상 지정하면 불법입니다.

  2. 기본 인수가있는 매개 변수는 매개 변수 목록의 끝에 연속 그룹을 형성해야합니다.

이제 C ++에서는 위의 요구 사항이 지속적으로 충족되는 한 함수 선언에서 다음 인수로 기본 인수를 갖는 매개 변수 집합을 "성장"할 수 있습니다.

예를 들어, 기본 인수없이 함수를 선언 할 수 있습니다

void foo(int a, int b);

이러한 선언 후 해당 함수를 호출하려면 두 인수를 명시 적으로 지정해야합니다.

동일한 번역 단위에서 나중에 (뒤로) 다시 선언 할 수 있지만 이번에는 하나의 기본 인수로 다시 선언 할 수 있습니다.

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

이 시점에서 하나의 명시 적 인수로 호출 할 수 있습니다.

더 나아가서 다시 한 번 더 기본 인수를 추가하여 다시 선언 할 수 있습니다

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

이 시점에서 명시적인 인수없이 호출 할 수 있습니다.

전체 예는 다음과 같습니다.

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)
{
  // ...
}

귀하의 질문에 대한 코드는 두 변종이 완벽하게 유효하지만 다른 의미를 갖습니다. 첫 번째 변형은 두 번째 매개 변수에 대한 기본 인수를 즉시 선언합니다. 두 번째 변형은 초기에 기본 인수없이 함수를 선언 한 다음 두 번째 매개 변수에 대해 하나를 추가합니다.

두 선언의 순 효과 (즉, 두 번째 선언 다음에 나오는 코드에서 보는 방식)는 정확히 동일합니다. 함수에는 두 번째 매개 변수에 대한 기본 인수가 있습니다. 그러나 첫 번째 선언과 두 번째 선언 사이에 일부 코드를 압축하면이 두 변형이 다르게 작동합니다. 두 번째 변형에서 함수에는 선언 사이에 기본 인수가 없으므로 두 인수를 명시 적으로 지정해야합니다.


귀하의 코드에서 정의한 void foo (int a = 1, int b)는 작동하지 않는다고 생각합니다. 하나의 선택적 매개 변수 뒤에 모든 선택적 매개 변수가 있어야합니다. 구문 오류입니다 (적어도 내 시스템의 g ++ 4.5.3에서는).
Nilesh

@Nilesh : 내가 명시 적으로 (이 예제의 요점이다)를 위해 위의 말했듯 void foo(int a = 1, int b)이 선언되어야 작동하는 void foo(int a, int b = 5) . 예, 작동합니다. 그리고 아니요, 구문 오류가 아닙니다. g ++ 4.5.3은 완벽하게 컴파일됩니다.
AnT

이제 함수는 이전 선언에서 b 값을 갖습니다. 지금 물건을 얻는 중. 감사합니다 :-)
Nilesh

1
@Nilesh : 예, 기본 인수 선언은 번역 단위의 모든 이전 선언에 누적됩니다.
AnT

1
변수 이름없이 함수 프로토 타입을 작성하고 싶습니다 int foo(int). int foo(int=5)매개 변수 이름을 제외하고 다시 쓸 수 있음을 알았습니다 . 아직 아무도 언급하지 않은 것 같습니다.
Victor Eijkhout

5

첫 번째 방법은 두 번째 방법보다 선호됩니다.

헤더 파일은 매개 변수가 선택적이며 기본값이 무엇인지 표시하기 때문입니다. 또한 해당 .cpp 파일의 구현에 관계없이 기본값이 동일하게됩니다.

두 번째 방법으로, 두 번째 매개 변수에 대한 기본값을 보장하지 않습니다. 해당 .cpp 파일이 구현되는 방법에 따라 기본값이 변경 될 수 있습니다.


4

기본 인수는 일반적으로 함수 프로토 타입에서 함수 이름이 처음 나타날 때 지정해야합니다. 함수 정의가 프로토 타입으로도 사용되므로 함수 프로토 타입이 생략 된 경우 함수 인수에 기본 인수를 지정해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.