На этот вопрос более чем адекватно ответили, но вы можете найти это полезным: Учебники по указателям на функции . Это по-настоящему всеобъемлющее изложение предмета в пяти главах!
Это очень популярная ошибка. Грамматика C ++ неоднозначна. Одно из правил разрешения двусмысленностей - «если что-то похоже на декларацию, это декларация». В этом случае вместо определения переменной вы объявили прототип функции.
string strA();
эквивалентен
string strA(void);
прототипу функции без аргументов, которая возвращает строку.
Если вы хотите явно вызвать конструктор без аргументов, попробуйте следующее:
string strA=string();
Это не полностью эквивалентно - это означает ' создать временную строку с помощью конструктора no-arg и затем скопировать ее для инициализации переменной strA ', но компилятору разрешено оптимизировать ее и опустить копирование.
РЕДАКТИРОВАТЬ: Вот соответствующий пункт в C ++ FAQ Lite
Он рассматривает
string strA();
как объявление функции.
Для использования конструктора по умолчанию:
string strA;
В C ++, как и в C, существует правило, согласно которому все, что выглядит как объявление, будет рассматриваться как объявление.
string strA();
выглядит как объявление функции, поэтому обрабатывается как один. Вам необходимо:
string strA;
Я не думаю, что в этом случае применимо правило «если это может быть объявление, оно считается объявлением». Поскольку далее обе вещи являются объявлениями
string a;
string a();
Одна - это объявление объекта, а другая - объявление функции. Правило применяется и в других случаях. Например, в этом случае:
string a(string());
В этом случае string ()
может означать две вещи.
строку
Здесь применяется fule, и string ()
означает то же, что и следующее, названное параметр (имена не имеют значения в параметрах при объявлении функции)
string a(string im_not_relevant());
Если функция принимает в качестве параметра массив или другую функцию, этот параметр распадается на указатель. В случае параметра функции - на указатель на функцию. Таким образом, это эквивалентно следующему, который может показаться более знакомым
string a(string (*im_not_relevant)());
. Но в вашем случае это скорее синтаксис, который мешает. В нем говорится, что следующее - объявление функции. Это никогда не может быть объявлением объекта (даже если это, вероятно, было задумано программистом!)
string a();
Таким образом, в этом контексте в первую очередь нет двусмысленности, и поэтому он объявляет функцию. Поскольку строка
имеет конструктор, определенный пользователем, вы можете просто опустить круглые скобки, и эффект останется таким же, как и предполагалось.
string a();
Таким образом, в этом контексте в первую очередь нет двусмысленности, и поэтому он объявляет функцию. Поскольку строка
имеет конструктор, определенный пользователем, вы можете просто опустить круглые скобки, и эффект останется таким же, как и предполагалось.
string a();
Таким образом, в этом контексте в первую очередь нет двусмысленности, и поэтому он объявляет функцию. Поскольку строка
имеет конструктор, определенный пользователем, вы можете просто опустить круглые скобки, и эффект останется таким же, как и предполагалось.
tkopec прав в том, почему это не работает. Чтобы ответить на ваш второй вопрос, вот как вы проверяете тип:
template<typename TEST> void Error_() {
TEST* MakeError = 1;
}
Вызвав Error_ (StrA);
, вы получите ошибку компиляции, и ваш компилятор, вероятно, сообщит вам, что это произошло в Error_
Теперь std :: basic_string> - это просто std :: string, так что это действительно означает Error_
. Часть между '<>' повторяется между '()', и это тип strA. В этом случае std :: string (*) (void)
.
Он печатает 1
, потому что указатели на функции всегда преобразуются в числовые как true
.
Компилятор интерпретирует string strA ()
как прототип функции функции, которая принимает пустые аргументы и возвращает объект строкового типа. Если вы хотите создать объект пустой строки, используйте string strA;
(без скобок)