使用临时对象调用构造函数

时间:2012-08-15 00:27:59

标签: c++ most-vexing-parse

我不明白以下问题。

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 个答案:

答案 0 :(得分:5)

你需要把它写成:

Box box((InnerBox()));

Box box{InnerBox()};

这不是MSVC特定的问题。 C ++中的规则是考虑任何可能是声明声明的构造。

如果没有附加括号,代码将声明一个名为box的函数,该函数返回Box,其单个参数是一个指向函数的指针,该函数不带参数并返回InnerBox 。 (是 - InnerBox()实际上在函数参数中使用时声明了一个指向函数(未命名)的指针(这类似于Box[]在使用时实际声明指向Box的方式作为函数参数))。

答案 1 :(得分:5)

对于名为'box'的函数,原始like被解析为函数声明(不是 definition ),该函数返回Box并将函数指针作为参数返回InnerBox并且不带参数InnerBox (*)()。有关最令人烦恼的解析问题的详细说明,请参阅this

您可以使用其他括号Box box((InnerBox()));明确区分对象构造。或者作为一种稍微更清晰的替代方法,您可以使用新的C ++ 11对象构造语法:

Box box{InnerBox()};

答案 2 :(得分:4)

  

这是一个特定于MSVC的问题,如果没有,有人可以解释这种语言的怪癖阻止我调用Box框(InnerBox()); ?

完成其他答案:

这称为most vexing parse。这对编译器来说不是问题。它基本上是一个解析规范,它表示可以作为声明处理的任何内容都被视为声明。

在您的情况下,您可以使用

进行修复
Box box((InnerBox()));