构造函数被解释为函数调用,并且直接跳过了构造函数

时间:2017-08-03 19:34:43

标签: c++ constructor move-constructor most-vexing-parse

我有一个包含4个构造函数的类,以及如下函数:

using namespace std;

class ABC {
public:
    ABC() {
        cout << "ABC()\n";
    }

    ABC(int) {
        cout << "ABC(int)\n";
    }

    ABC(ABC&) {
        cout << "ABC(&)\n";
    }

    ABC(ABC&&) {
        cout << "ABC(&&)\n";
    }
};


void ff(ABC t) { }

请帮我解释一些对我来说很奇怪的行为(我使用MSVC 2016进行编译):

1)为什么我会收到警告C4930:&#34;&#39; ABC a1(ABC(__ cdecl *)(void))&#39;:未调用原型函数(是否有变量定义?)& #34;使用以下代码:

void main() {
    ABC a1(ABC());
    ff(ABC(5));
}

在执行时,我希望得到以下输出:

ABC()
ABC(&&)
ABC(int)
ABC(&&)

但我真正得到的是

ABC(int)

2)现在如果我改为

void main() {
    ABC a1(ABC(5));
    ff(ABC(5));
}

没有更多的警告。但在执行时,我期望得到的是

ABC(int)
ABC(&&)
ABC(int)
ABC(&&)

但我真正得到的是

ABC(int)
ABC(int)

3)现在

void main() {
    ABC( ABC() );
    ff(ABC(5));
}

它甚至无法编译。我收到错误C2660:&#34;&#39; ABC&#39;:函数不带1个参数&#34;。

4)最后,为什么以下编译而3)没有?

void main() {
    ff(ABC(5));
}

1 个答案:

答案 0 :(得分:5)

由于问题称为most vexing parse in C++,行

ABC a1(ABC());

a1声明为返回类型为ABC且其参数类型为不带参数的函数并返回ABC的函数。

该行

ABC(ABC());

更难以剖析,但它也是函数的声明,而不是变量的定义。

int(a);

是变量a的有效声明。它与:

相同
int a;

同样,ABC的行与:

相同
ABC ABC();

这里ABC意味着重载。第一个ABC是类型名称。第二个ABC是函数名称(由于最令人烦恼的解析)。它声明ABC是一个不带参数的函数,并返回类型为ABC的对象。对于函数的其余部分,ABC是函数名称,而不是类型名称。因此,

ff(ABC(5));

无效,因为在该上下文中ABC是一个不带参数的函数。

我没有回答为什么移动构造函数不会被调用的问题。