程序在3个主要的C ++编译器中被编译得不同。 哪一个是对的?
作为一个有趣的后续(虽然没有很大的实际重要性)到我以前的问题: 为什么C ++允许我们在声明variables时在括号中包围variables名?
我发现将括号中的声明与注入的类名称function组合在一起可能会导致令人惊讶的编译器行为结果。
看看下面的程序:
#include <iostream> struct B { }; struct C { C (){ std::cout << "C" << '\n'; } C (B *) { std::cout << "C (B *)" << '\n';} }; B *y = nullptr; int main() { C::C (y); }
-
用g ++编译4.9.2给了我下面的编译错误:
main.cpp:16:10: error: cannot call constructor 'C::C' directly [-fpermissive]
-
它使用MSVC2013 / 2015成功编译并打印
C (B *)
-
它与叮当3.5编译成功,并打印
C
所以强制性的问题是哪一个是对的? 🙂
(我强烈地向铿锵的版本,而msvc的方式来停止声明variables后,只是改变types与技术上它的typedef似乎有点奇怪)
GCC是正确的,至less根据C ++ 11的查找规则。 3.4.3.1 [class.qual] / 2指定如果嵌套名称说明符与类名称相同,则表示构造函数不是注入的类名称。 举例说明:
B::A ba; // object of type A A::A a; // error, A::A is not a type name struct A::A a2; // object of type A
它看起来像MSVC曲解它作为函数风格的转换expression式创build一个临时C
与y
作为构造函数参数; 而Clang把它误解为一个叫做C
的variables的声明。
G ++是正确的,因为它提供了一个错误。 因为构造函数不能以没有new
运算符的格式直接调用。 虽然你的代码调用C::C
,但它看起来像一个构造函数调用。 但是,根据C ++ 11标准3.4.3.1,这不是一个合法的函数调用,也不是一个types名称( 见Mike Seymour的答案 )。
铛是错误的,因为它甚至没有调用正确的function。
MSVC是合理的,但仍然不符合标准。