Вызов конструктора с временным объектом
Я не понимаю следующей проблемы.
class InnerBox
{
public:
InnerBox() : mContents(123) { };
private:
int mContents;
};
class Box
{
public:
Box(const InnerBox& innerBox) : mInnerBox(innerBox) { };
private:
InnerBox mInnerBox;
};
void SomeFunction(const Box& box)
{
return;
}
int main()
{
Box box(InnerBox()); // !!PROBLEM!! Doesn't work: compiler thinks this is a function declaration
SomeFunction(box); // Error, cannot convert 'function pointer type' to const Box&
return 0;
}
Полное сообщение об ошибке (Visual Studio 2010)
error C2664: 'SomeFunction' : cannot convert parameter 1 from 'Box (__cdecl *)(InnerBox (__cdecl *)(void))' to 'const Box &'
Исправление простое:
int main()
{
InnerBox innerBox;
Box box(innerBox);
SomeFunction(box);
return 0;
}
Является ли это специфической проблемой MSVC, и если нет, Может ли кто-то объяснить, что причуда языка мешает мне позвонить Box box(InnerBox());
?
3 ответа:
Вам нужно записать его как:
Box box((InnerBox()));
Или
Box box{InnerBox()};
Это не специфическая проблема MSVC. Правило в C++ состоит в том, чтобы рассматривать любую конструкцию, которая может быть объявлением, как объявление.
Без дополнительных скобок код объявляет функцию под названиемbox
, которая возвращаетBox
и единственный аргумент которой является указателем на функцию, не принимающую никаких аргументов и возвращающуюInnerBox
. (Да --InnerBox()
фактически объявляет указатель на функцию (без имени), когда используется в параметре функции (это похоже на то, какBox[]
фактически объявляет указатель наBox
при использовании в качестве параметра функции)).
Исходный like анализируется как функцияобъявление (Неопределение ) для функции с именем 'box', которая возвращает Box и принимает в качестве параметра указатель функции, который возвращает InnerBox и не принимает параметров
InnerBox (*)()
. Смотрите это для хорошего описания самой неприятной проблемы синтаксического анализа.Вы можете явно дифференцировать конструкцию объекта с помощью дополнительных скобок
Box box((InnerBox()));
. Или в качестве слегка более чистой альтернативы вы можете использовать новый синтаксис построения объектов C++11:
Box box{InnerBox()};
Является ли это специфической проблемой MSVC, и если нет, Может ли кто-нибудь объяснить, какая причуда языка мешает мне вызвать Box box(InnerBox()); ?
Для завершения других ответов:
Это известно как самый досадный разбор. Это не проблема с компилятором. Это в основном спецификация синтаксического анализа, которая говорит, что все, что может рассматриваться как объявление, рассматривается как объявление.
В вашем случае вы можете исправить это с помощью
Box box((InnerBox()));