函数名称为什么不能与返回名称类型相同?

tenspd137

不知道我缺少什么,但是为什么不编译呢?

class Game
{
};

class Actor
{
   Game* mGame;
   Game* Game() { return mGame; }
};

int main()
{
  Actor a();

  return 0;
}

g ++ -std = c ++ 17 main.cpp -o测试

main.cpp:8:10: error: declaration of ‘Game* Actor::Game()’ changes meaning of ‘Game’ [-fpermissive]
    8 |    Game* Game() { return mGame; }
      |          ^~~~
main.cpp:1:7: note: ‘Game’ declared here as ‘class Game’
    1 | class Game
      |      

显然,如果我将功能更改为GetGame,就没有问题。只想知道为什么-我想念什么?

谢谢!

弗朗西斯·库格勒

使用您当前的代码,我使用各种编译器Compiler Explorer上对其进行了测试...

这是3种不同编译器的结果,它们生成的程序集以及可能的错误或警告。所有编译器选项均设置为-std=c++17 -O3


x86-64 lang声(trunk)

汇编

main:                                   # @main
        xor     eax, eax
        ret

警告-错误

warning: empty parentheses interpreted as a function
declaration [-Wvexing-parse]

其中a();被突出显示为有问题的警告


x86-64 gcc(中继)

编译失败!

警告-错误

error: declaration of 'Game*' Actor::Game()' changes meaning of
'Game' [-fpermissive]

其中Game()被突出显示为有问题的错误


x64 msvc v19.24

汇编

main    PROC
        xor     eax, eax
        ret     0
main    ENDP

警告-错误

warning C4930: 'Actor a(void)': prototyped function not called
(was a variable definition intended?)

其中Actor a();被突出显示为有问题的警告



这些是基于您当前代码的结果。现在让我们看一下这3个相同的示例,只修改您的一小段代码...

我将把Actor a();您的main函数Actor a{};改为,让我们看一下区别...



x86-64 lang声(trunk)

汇编

main:                                   # @main
        xor     eax, eax
        ret

警告-错误

没有!


x86-64 gcc(中继)

编译失败!

警告-错误

error: declaration of 'Game*' Actor::Game()' changes meaning of
'Game' [-fpermissive]

其中Game()被突出显示为有问题的错误。


x64 msvc v19.24

汇编

a$ = 0
main    PROC
$LN3:
        push    rdi
        sub     rsp, 16
        lea     rax, QWORD PTR a$[rsp]
        mov     rdi, rax
        xor     eax, eax
        mov     ecx, 8
        rep stosb
        xor     eax, eax
        add     rsp, 16
        pop     rdi
        ret     0
main    ENDP

警告-错误

没有!



评定

如果你比较一下3,你会看到,无论ClangMSVC将在这两种情况下进行编译,但是,他们都将给予警告对于第一种情况,并会无错地编译第二。GCC另一方面,在两种情况下均无法编译,并且生成相同的确切警告或编译器错误。

在第一种情况下,它是您的原始来源,Clang并且MSVC能够确定您要调用所述类的构造函数,Actor但是会生成警告消息,其中GCC在使用()运算符时无法将其全部编译在一起GCC无法确定您是否要致电Actor::Game()Game::Game()

我们还可以推断出ClangMSVC都从第一种情况指向警告,a()在两种情况下GCC都将其错误指向Game()

要检查什么更是怎么回事,在第一种情况下,无论是ClangMSVC正在产生几乎相同的组件。在第二种情况下,Clang仍然会生成相同的程序集,但是MSVC占用空间是一个完全不同的故事!

根据我之间的比较,我可以根据目前的知识说些什么,而无需进行更多研究

Actor a();

Actor a{};

从生成的警告,错误和汇编代码中看到的行为是这样的...

我相信这可能会Implementation Defined跨越不同的编译器。

我不能说是否UB,但是我可能会怀疑在某些情况下您可以从上面生成的程序集,警告和错误中看到...

如果将()运算符用于类的构造函数,则这三个编译器之间至少存在一些歧义。GCC甚至不会编译并生成错误。ClangMSVC这两种编译其中Clang给出了空括号被解释为函数声明警告,并MSVC给予警告,原型函数没有被调用。

但是,当我们切换到{}运算符或初始化程序列表时,将Clang生成与之前相同的程序集,但不再生成警告。MSVCinstructions似乎正在构造这两个类并且不产生任何警告的位置进行了彻底的设置GCC在这两种情况下都会出现错误,并说:“我放弃了您的意图”,这是我始终指向的错误消息Game()



结论

因此,回答您的问题:

函数名称为什么不能与返回名称类型相同?

根据使用环境和所使用的编译器,它可能是相同的,对于其他编译器,他们可能会或将拒绝它。

那么谁能说哪个编译器的解释是正确和正确的...我没有的副本,standard所以我无法再深入探讨这一language-lawyer部分了,但是我可以概括正在发生的事情以及发生的原因。刚刚证明。

我希望这种推理可能对您的命名约定有所帮助,并希望编译器在尝试将这些名称和符号转换为对象时如何尝试解释这些名称和符号。

因此,在某些情况下可能存在歧义,而在其他情况下则不会存在歧义。这使我相信这是跨编译器定义的实现,因为AFAIK该标准不需要特定的符号,name-reuse并且可能导致UB因此,这不是好习惯,绝对不是代码异味!

所有这些都与硬件架构无​​关!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么事件模糊不能与函数名称模糊一起使用?

为什么在类中不能将函数名称和变量名称称为同一事物?

为什么Typescript函数类型签名包含参数名称

为什么打印函数名称会返回值?

函数名称相同,参数类型不同

为什么类型特征不能与名称空间范围中的类型一起使用?

“成员名称不能与其封闭类型相同”是什么意思?

为什么C ++函数模板实例化的返回类型包含在错误的函数名称中?

错误:成员名称不能与其封闭类型相同

在类声明中,为什么构造函数中的参数不能与私有部分中定义的变量具有相同的名称?

JavaScript-为什么我不能将变量称为“名称”?

在C函数声明中,返回类型和函数名称之间会出现什么?

为什么在这种情况下不能将函数名称作为参数传递?

为什么不能在数据结构中导入函数名称

为什么我的返回类型不能与void *协变?

为什么参数名称不能以数字开头?

为什么必须在TS函数类型中指定参数名称?

为什么我的函数不接受Colors类型的参数名称?

名称为“ count”的计数列返回多行。为什么?

为什么构造函数中的全局变量和参数变量不能具有相同的名称?

为什么类方法不能使用相同的名称调用全局函数?

为什么我的JavaScript函数名称冲突?

为什么我可以省略函数的参数名称?

为什么在函数名称上使用与号?

为什么EXE文件中有文本函数名称?

为什么不允许数字函数名称?

为什么KCacheGrind不显示我的函数名称?

为什么箭头函数名称必须为const / let?

产品风味名称不能与构建类型名称冲突