C 함수 선언자
우선, C가 있습니다. C에서는 A a()함수 선언입니다. 예를 들어 putchar다음과 같은 선언이 있습니다. 일반적으로 이러한 선언은 헤더 파일에 저장되지만 함수 선언이 어떻게 보이는지 알면 수동으로 작성하는 것을 막을 수있는 것은 없습니다. 인수 이름은 선언에서 선택 사항이므로이 예제에서는 생략했습니다.
int putchar(int);
이를 통해 이와 같은 코드를 작성할 수 있습니다.
int puts(const char *);
int main() {
puts("Hello, world!");
}
C를 사용하면 함수 호출처럼 보이는 읽기 쉬운 구문으로 함수를 인수로 취하는 함수를 정의 할 수 있습니다 (함수에 대한 포인터를 반환하지 않는 한 읽을 수 있습니다).
#include <stdio.h>
int eighty_four() {
return 84;
}
int output_result(int callback()) {
printf("Returned: %d\n", callback());
return 0;
}
int main() {
return output_result(eighty_four);
}
앞서 언급했듯이 C는 헤더 파일에서 인수 이름을 생략 할 수 있으므로 헤더 파일에서 output_result이와 같이 보입니다.
int output_result(int());
생성자에서 하나의 인수
당신은 그것을 인식하지 못합니까? 글쎄, 내가 당신을 생각 나게합니다.
A a(B());
네, 정확히 같은 함수 선언입니다. Ais int, ais output_result및 Bis int입니다.
C의 새로운 기능과 C의 충돌을 쉽게 알 수 있습니다. 정확히 말하자면 생성자는 클래스 이름과 괄호이며 ()대신을 사용 하는 대체 선언 구문 입니다 =. 의도적으로 C ++은 C 코드와 호환되도록 노력하므로 실제로는 아무도 신경 쓰지 않아도이 경우를 처리해야합니다. 따라서 이전 C 기능은 새로운 C ++ 기능보다 우선합니다. 선언 문법은 ()실패하면 새 구문으로 되돌리기 전에 이름을 함수로 일치시킵니다 .
이러한 기능 중 하나가 존재하지 않거나 다른 구문 ( {}C ++ 11 과 같이 )이있는 경우이 문제는 인수가 하나 인 구문에 대해서는 발생하지 않았을 것입니다.
이제 왜 A a((B()))작동 하는지 물어볼 수 있습니다. output_result쓸모없는 괄호로 선언하자 .
int output_result((int()));
작동하지 않습니다. 문법에서는 변수가 괄호 안에 있지 않아야합니다.
<stdin>:1:19: error: expected declaration specifiers or ‘...’ before ‘(’ token
그러나 C ++은 표준 표현을 기대합니다. C ++에서는 다음 코드를 작성할 수 있습니다.
int value = int();
그리고 다음 코드는.
int value = ((((int()))));
C ++은 괄호 안의식이 C 형과 달리식이 될 것으로 기대합니다. 괄호는 여기서 의미가 없습니다. 그러나 쓸모없는 괄호를 삽입하면 C 함수 선언이 일치하지 않고 새 구문을 올바르게 일치시킬 수 있습니다 (예 :와 같은 표현식이 필요함 2 + 2).
생성자에서 더 많은 인수
분명히 하나의 주장은 좋지만 두 가지는 어떻습니까? 생성자가 인수를 하나만 가질 수있는 것은 아닙니다. 두 개의 인수를 취하는 내장 클래스 중 하나는std::string
std::string hundred_dots(100, '.');
이것은 모두 훌륭하고 훌륭합니다 (기술적으로,로 작성된다면 대부분의 vexing 구문 분석이 필요합니다 std::string wat(int(), char()). 그러나 솔직히 말하십시오-누가 그것을 쓸까요 ?하지만이 코드에 vexing 문제가 있다고 가정합시다. 괄호 안의 모든 것.
std::string hundred_dots((100, '.'));
그렇지 않습니다.
<stdin>:2:36: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
In file included from /usr/include/c++/4.8/string:53:0,
from <stdin>:1:
/usr/include/c++/4.8/bits/basic_string.tcc:212:5: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ [-fpermissive]
basic_string<_CharT, _Traits, _Alloc>::
^
g ++ 시도 변환하는 이유는 확실하지 않다 char에 const char *. 어느 쪽이든, 생성자는 하나의 값 유형으로 만 호출되었습니다 char. type의 인수가 하나 인 오버로드가 없으므로 char컴파일러가 혼동됩니다. 당신은 물어볼 수 있습니다-왜 인자가 char 타입입니까?
(100, '.')
예, ,여기에 쉼표 연산자가 있습니다. 쉼표 연산자는 두 개의 인수를 사용하여 오른쪽 인수를 제공합니다. 그것은 실제로 유용하지는 않지만 내 설명으로 유명합니다.
대신 가장 까다로운 구문 분석을 해결하려면 다음 코드가 필요합니다.
std::string hundred_dots((100), ('.'));
인수는 전체 표현식이 아닌 괄호 안에 있습니다. 실제로 C ++ 기능을 사용하려면 C 문법을 약간 벗어나면 식 중 하나만 괄호 안에 있어야합니다. 일이 우리에게 논쟁의 여지가없는 지점으로 인도합니다.
생성자의 인수 없음
eighty_four내 설명 에서 기능을 발견했을 수도 있습니다 .
int eighty_four();
예, 이것은 또한 가장 까다로운 구문 분석의 영향을받습니다. 유효한 정의이며 헤더 파일을 만들었을 때 가장 많이 본 것입니다. 괄호를 추가해도 문제가 해결되지 않습니다.
int eighty_four(());
왜 이렇게이다? 글쎄, ()표현이 아닙니다. C ++에서는 괄호 안에 식을 넣어야합니다. 아무것도 의미하지 않기 auto value = ()때문에 C ++로 작성할 수 없습니다 ()(빈 터플과 같은 경우에도 (파이썬 참조), 0이 아닌 하나의 인수가됩니다). 실제로 이것은 {}괄호 안에 넣을식이 없으므로 함수 선언에 대한 C 문법이 항상 적용되므로 C ++ 11의 구문을 사용하지 않으면 서 속기 구문을 사용할 수 없습니다 .
(B())C ++ 표현식 일뿐입니다. 예외는 아닙니다. 유일한 차이점은 유형으로 구문 분석 될 수있는 방법이 없다는 것입니다.