- 令我惊讶的是,C++ 对象的名称可以与类名相同。有人能解释一下原因吗?
- 当我将类
a
的对象声明为a a1()
时,它不会引发错误,但也没有调用构造函数。这是为什么?
我的代码:
#include<iostream>
using namespace std;
class a
{
public:
a()
{
cout << "in a\n";
}
};
int main()
{
a a1();
a a;
}
a
的对象声明为 a a1()
时,它不会引发错误,但也没有调用构造函数。这是为什么?我的代码:
#include<iostream>
using namespace std;
class a
{
public:
a()
{
cout << "in a\n";
}
};
int main()
{
a a1();
a a;
}
a a1();
的时候,实际上它被解析为一个函数声明而不是对默认构造函数的调用。a a1;
则可以正确地调用默认构造函数。a a;
时,它可以工作,因为变量名优先于类名,在所谓的名称隐藏中。尽管它可以工作,但只会导致混淆,我建议避免这样做。a
的定义隐藏了类型名称,以避免与外部(包含)名称的干扰。 - Nobody moving away from SEa a1();
是一个函数声明。
这是在C++11中创建统一初始化的重要原因。要使用构造函数初始化对象,请使用 a a1{};
3.3.10
Name hiding段落2,它说(重点在于我):“在同一作用域中声明的变量、数据成员、函数或枚举器的名称可以隐藏类名(9.1)或枚举名(7.2)。如果在同一作用域中以任何顺序声明了类或枚举名和变量、数据成员、函数或枚举器具有相同的名称,则无论变量、数据成员、函数或枚举器名称在何处可见,都会隐藏类或枚举名。”a a1();
你也可以使用这个旧版本的C++11:
a a1 ;
a a1{} ;
clang
都会用下面的代码来警告你:int main()
{
a a;
a a2 ;
}
main.cpp:12:10: note: class 'a' is hidden by a non-type declaration of 'a' here
a a;
^
gcc
获得类似的警告。
更新
考虑到我之前在统一初始化的缺陷中所做的评论,我意识到如果你怀疑a1
不是正确的类型,你可以使用typeid来调试发生了什么。例如,这段代码:std::cout << typeid(a).name() << std::endl ;
std::cout << typeid(a1).name() << std::endl ;
在 Coliru 实时示例 中,会产生以下输出结果:
1a
F1avE
通过 c++filt 进行转换,你将得到以下输出:
a () // A function that returns type a
a // type a
我尝试使用clang
编译您的代码,得到了这个结果,我认为它已经说明了一切。
test.cpp:15:9: warning: empty parentheses interpreted as a function declaration
[-Wvexing-parse]
a a1();
^~
test.cpp:15:9: note: remove parentheses to declare a variable
a a1();
^~
1 warning generated.
a a1();
是一个函数声明,返回类型为 a
,与调用构造函数无关。
a a;
是一个简单的语句,可以正常工作并调用构造函数。
a1
不是一个对象,而是一个函数。 - Luchian Grigore