Вы неправильно используете Ajax. Идея состоит в том, чтобы не возвращать что-либо, а вместо этого передавать данные на вызов, называемый функцией обратного вызова, которая обрабатывает данные.
То есть:
function handleData( responseData ) {
// Do what you want with the data
console.log(responseData);
}
$.ajax({
url: "hi.php",
...
success: function ( data, status, XHR ) {
handleData(data);
}
});
Возвращение чего-либо в обработчике ничего не сделает. Вы должны либо передавать данные, либо делать то, что хотите, непосредственно внутри функции успеха.
Нет просветленного ответа, это просто потому, что он не определен как корректный синтаксис языка C ++ ... Так оно и есть, по определению языка.
Если у вас есть выражение внутри то оно действительно. Например:
((0));//compiles
Еще проще: потому что (x)
является допустимым выражением C ++, а ()
- нет.
Чтобы узнать больше о том, как определяются языки и как работают компиляторы, вы должны узнать о теории формальных языков или более конкретно Контекст-бесплатные грамматики (CFG) и родственные материалы, такие как машины с конечным состоянием. Если вас это интересует, хотя страниц в википедии недостаточно, вам нужно будет получить книгу.
Прежде всего, существует 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());
Да, это точно такое же объявление функции. A
- int
, a
- output_result
, а B
- 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, '.');
. Все это хорошо и прекрасно (технически, он имел бы самый неприятный синтаксический анализ, если бы он был записан как std::string wat(int(), char())
, но давайте будем честными - кто бы это написал? Но давайте предположим, что этот код имеет неприятную проблему. Предположим, что вам нужно все положить в круглые скобки.
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
. Нет перегрузки, которая имеет один аргумент типа char
, поэтому компилятор запутан. Вы можете спросить - почему аргумент имеет тип char?
(100, '.')
Да, ,
здесь - запятый оператор. Оператор запятой принимает два аргумента, и дает аргумент правой стороны. Это не очень полезно, но это то, что нужно знать для моего объяснения.
Вместо этого, чтобы решить самый неприятный синтаксический разбор, необходим следующий код.
std::string hundred_dots((100), ('.'));
Аргументы находятся в круглых скобках, а не t все это выражение. Фактически, только одно из выражений должно быть в круглых скобках, так как достаточно немного сломать C-грамматику, чтобы использовать функцию C ++. Вещи приводят нас к нулевым аргументам.
Возможно, вы заметили функцию eighty_four
в моем объяснении.
int eighty_four();
Да, на это также влияет самый неприятный синтаксический разбор. Это правильное определение, и вы, скорее всего, видели, если создали файлы заголовков (и вам нужно). Добавление скобок не исправляет.
int eighty_four(());
Почему это так? Ну, ()
не является выражением. В C ++ вы должны поставить выражение между круглыми скобками. Вы не можете писать auto value = ()
в C ++, потому что ()
ничего не значит (и даже если бы это было так, как пустой кортеж (см. Python), это был бы один аргумент, а не ноль). Практически это означает, что вы не можете использовать сокращенный синтаксис без использования синтаксиса {}
C ++ 11, так как в круглых скобках нет выражений, а C-грамматика для деклараций функций всегда будет применяться.
Окончательное решение этой проблемы состоит в том, чтобы перейти к синтаксису синтаксиса C + 11, если вы можете.
A a{};
Самые внутренние парсеры в вашем примере будут выражением, а в C ++ грамматика определяет expression
как assignment-expression
или другой expression
, за которым следует запятая, а другая assignment-expression
(Приложение A.4 - Грамматика / Выражения).
Грамматика далее определяет assignment-expression
как один из нескольких других типов выражения, ни один из которых не может быть ничем (или только пропуском).
So причина, по которой вы не можете A a(())
, просто потому, что грамматика этого не позволяет. Тем не менее, я не могу ответить, почему люди, которые создали C ++, не позволяли этому конкретному использованию пустых парнеров как своего рода особый случай - я бы предположил, что они предпочли бы не вставлять такой особый случай, если бы разумная альтернатива.
Вы могли бы вместо
A a(());
использовать
A a=A();