Вызов конструктора с временным объектом
Я не понимаю следующей проблемы.
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()));