这怎么可能在 c++ 中使用

How is this possible to use in c++?

本文关键字:c++ 怎么可能      更新时间:2023-10-16
  1. 令我惊讶的是,我发现 c++ 对象的名称可以与类名相同。有人可以向我解释原因吗?
  2. 当我将类 a 的对象声明为 a a1() 时,它不会引发错误,但不调用构造函数。为什么会这样?

我的代码:

#include<iostream>
using namespace std;
class a 
{
    public:
    a() 
    {
        cout << "in an";
    }
};
int main()
{
    a a1();
    a a;
}

当你编写a a1();时,它实际上被解析为函数声明,而不是对默认构造函数的调用。

a a1;

将正确调用默认构造函数

当你写a a;它有效时,因为在所谓的名称隐藏中,变量名称优先于类名,但即使它有效,也只会导致混淆,我会避免这样做。

对于所有喜欢标准报价的人,你去这里

类名 (9.1( 或枚举名 (7.2( 可以通过在同一作用域中声明的变量、数据成员、函数或枚举器的名称隐藏。如果类或枚举名称以及变量、数据成员、函数或枚举器在同一作用域(以任意顺序(声明,则在变量、数据成员、函数或枚举器名称可见的任何位置,类或枚举名称都将隐藏。

a a1();是一个函数声明。

这是在 C++11 中创建统一初始化的重要原因。若要使用 C++11 中的构造函数初始化对象,请使用 a a1{};

如果您查看C++草案标准部分,实际上隐藏带有变量的类的名称是有效的3.3.10 名称隐藏段落 2 说(强调我的(:

类名 (9.1( 或枚举名 (7.2( 可以通过在同一作用域中声明的变量、数据成员、函数或枚举器的名称隐藏。如果类或枚举名称以及变量、数据成员、函数或枚举器在同一作用域(按任意顺序(声明,则在变量、数据成员、函数或枚举器名称所在的位置上,类或枚举名称将隐藏 可见。

我不认为这是好的做法,它会导致难以维护代码。这行代码实际上是在声明一个函数:

a a1();

您也可以使用此 pre-C++11

a a1 ;

C++11 中引入的统一初始化:

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

> a a1(); 是函数声明返回类型,作为 a 与调用构造函数无关

a 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.