C++ 什么';在这个匿名类(变量)声明中到底发生了什么?
正在尝试编译:C++ 什么';在这个匿名类(变量)声明中到底发生了什么?,c++,C++,正在尝试编译: class AnonymousClass { public: AnonymousClass(int x) { } }; int main() { int x; AnonymousClass(x); return 0; } 从MSVC生成错误: foo.cpp(13) : error C2371: 'x' : redefinition; different basic types foo.cpp(12) : see d
class AnonymousClass
{
public:
AnonymousClass(int x)
{
}
};
int main()
{
int x;
AnonymousClass(x);
return 0;
}
从MSVC生成错误:
foo.cpp(13) : error C2371: 'x' : redefinition; different basic types
foo.cpp(12) : see declaration of 'x'
foo.cpp(13) : error C2512: 'AnonymousClass' : no appropriate default constructor available
g++的错误消息类似:
foo.cpp: In function ‘int main()’:
foo.cpp:13: error: conflicting declaration ‘AnonymousClass x’
foo.cpp:12: error: ‘x’ has a previous declaration as ‘int x’
foo.cpp:12: warning: unused variable ‘x’
通过给
AnonymousClass
对象一个明确的名称,它很容易修复,但是这里发生了什么,为什么?我认为这是一种声明语法的怪异(就像在COMP.Lang.C++FAQ中描述的情况),但我不熟悉这个。 你缺少变量/对象的实际名称:
AnonymousClass myclass(x);
与其这样,不如写
AnonymousClass (myclass)(x);
因此,您的代码行会产生以下结果:
AnonymousClass (x);
或更常见的:
AnonymousClass x;
为什么会这样?括号仅用于逻辑分组(“什么属于一起?”)。唯一的区别是,它们被强制用于参数(即,您不能只编写匿名类myclass x
)
它定义了一个AnonymousClass
类型的变量x
。这就是为什么会出现重新定义错误,因为x
已声明为int
括号是多余的。您可以添加更多大括号,如:
AnonymousClass(x);
AnonymousClass((x));
AnonymousClass(((x)));
AnonymousClass((((x))));
//and so on
它们都是相同的:
AnonymousClass x;
演示:
您可以使用语法
A(x)
创建匿名对象,尤其是在调用函数时:
int x = 10;
f(A(x)); //1 - () is needed
f(A((((x))))); //2 - extra () are superfluous
行1
和2
调用函数f
传递类型a
的对象:
但是,第2行的额外括号仍然是多余的。为了避免这样的错误,请记住一条规则:如果您用一个参数声明匿名对象,只需将它放在一对括号中一个类似的问题:啊,是的,在函数指针声明的典型情况下,符号名称周围的括号显然是合法的。是的。您还可以通过强制将
匿名类(x)
作为子表达式来防止将其视为x
的定义。例如(void)匿名类(x)代码>。从语法上讲,这不可能是一个定义,因此它是一个表达式语句,使用一个参数构造函数创建一个对象,然后销毁它。相关:它们不仅仅用于分组。你不能随意添加括号。类型周围的括号和带有关键字的括号具有特殊含义。你不能在关键字周围加括号等等。我真的想知道为什么在声明中变量名周围都允许使用括号。在类型周围添加括号是不同的,因为这将被解释为强制转换。围绕关键字它们没有任何意义,但围绕实际(变量名)它们对逻辑分组有意义(参见Nawaz的答案;例如告诉编译器*
属于何处)。好的,谢谢。除了声明函数指针之外,允许在声明的名称周围使用括号是否有用?@jamesdlin:正如我所说,在声明变量时,括号是多余的。但在声明函数指针时,它们并不是多余的;那是必要的A(*x)(
与A*x()
具有不同的含义。前者声明一个函数指针,后者是一个函数声明(原型)。@Nawaz:我上面的评论问它们是否对函数指针以外的任何东西有用。@jamesdlin:我想,多余这个词解释了它在声明变量时没有用。相反,它增加了混乱。@jamesdlin:paren还用于声明数组引用和指针。例如,AnonymousClass*ptr[3]
的类型与AnonymousClass(*ptr)[3]
不同。实际上,对于特殊情况,不允许使用奇怪的语法——对于简单类型,有一种通用语法恰好是奇怪的(因为它似乎与表达式中的含义不明确,即使用1 arg构造临时语法)。
int x = 10;
f(A(x)); //1 - () is needed
f(A((((x))))); //2 - extra () are superfluous