4

我不明白下面的问题。

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());吗?

4

3 回答 3

5

你需要把它写成:

Box box((InnerBox()));

或者

Box box{InnerBox()};

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

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

于 2012-08-15T00:29:59.990 回答
5

原来的 like 被解析为一个名为 'box' 的函数的函数声明(而不是定义),该函数返回一个 Box 并将返回 InnerBox 且不带参数的函数指针作为参数InnerBox (*)()。有关最令人烦恼的解析问题的详细描述,请参阅this

您可以使用附加括号明确区分您的对象构造Box box((InnerBox()));。或者作为一种更简洁的替代方案,您可以使用新的 C++11 对象构造语法:

Box box{InnerBox()};

于 2012-08-15T00:33:32.560 回答
4

这是一个 MSVC 特定的问题吗?如果不是,有人可以解释一下语言的什么怪癖阻止我调用 Box box(InnerBox()); ?

要完成其他答案:

这被称为最令人烦恼的解析。这不是编译器的问题。它基本上是一个解析规范,它说任何可以被视为声明的东西都被视为声明。

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

Box box((InnerBox()));
于 2012-08-15T00:36:57.273 回答