不知道我缺少什么,但是为什么不编译呢?
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,你会看到,无论Clang
和MSVC
将在这两种情况下进行编译,但是,他们都将给予警告对于第一种情况,并会无错地编译第二。GCC
另一方面,在两种情况下均无法编译,并且生成相同的确切警告或编译器错误。
在第一种情况下,它是您的原始来源,Clang
并且MSVC
能够确定您要调用所述类的构造函数,Actor
但是会生成警告消息,其中GCC
在使用()
运算符时无法将其全部编译在一起。GCC
无法确定您是否要致电Actor::Game()
或Game::Game()
。
我们还可以推断出Clang
和MSVC
都从第一种情况指向警告,a()
而在两种情况下GCC
都将其错误指向Game()
。
要检查什么更是怎么回事,在第一种情况下,无论是Clang
和MSVC
正在产生几乎相同的组件。在第二种情况下,Clang
仍然会生成相同的程序集,但是MSVC
占用空间却是一个完全不同的故事!
根据我之间的比较,我可以根据目前的知识说些什么,而无需进行更多研究
Actor a();
和
Actor a{};
从生成的警告,错误和汇编代码中看到的行为是这样的...
我相信这可能会Implementation Defined
跨越不同的编译器。
我不能说是否UB
,但是我可能会怀疑在某些情况下您可以从上面生成的程序集,警告和错误中看到...
如果将()
运算符用于类的构造函数,则这三个编译器之间至少存在一些歧义。GCC
甚至不会编译并生成错误。Clang
而MSVC
这两种编译其中Clang
给出了空括号被解释为函数声明警告,并MSVC
给予警告,原型函数没有被调用。
但是,当我们切换到{}
运算符或初始化程序列表时,将Clang
生成与之前相同的程序集,但不再生成警告。MSVC
对instructions
似乎正在构造这两个类并且不产生任何警告的位置进行了彻底的设置。GCC
在这两种情况下都会出现错误,并说:“我放弃了您的意图”,这是我始终指向的错误消息Game()
!
结论
因此,回答您的问题:
函数名称为什么不能与返回名称类型相同?
根据使用环境和所使用的编译器,它可能是相同的,对于其他编译器,他们可能会或将拒绝它。
那么谁能说哪个编译器的解释是正确和正确的...我没有的副本,standard
所以我无法再深入探讨这一language-lawyer
部分了,但是我可以概括正在发生的事情以及发生的原因。刚刚证明。
我希望这种推理可能对您的命名约定有所帮助,并希望编译器在尝试将这些名称和符号转换为对象时如何尝试解释这些名称和符号。
因此,在某些情况下可能存在歧义,而在其他情况下则不会存在歧义。这使我相信这是跨编译器定义的实现,因为AFAIK
该标准不需要特定的符号,name-reuse
并且可能导致UB
!因此,这不是好习惯,绝对不是代码异味!
所有这些都与硬件架构无关!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句