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

Calling constructor with a temporary object

本文关键字:构造函数 调用 临时对象      更新时间:2023-10-16

我不明白以下问题。

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

你需要把它写成:

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