为什么这个程序调用operator()而不是构造函数? [英] Why does this program call operator () instead of the constructor?
问题描述
这里是一个程序,编译没有警告例如。 GNU C ++:
$ g ++ -ot -Wall -pedantic -Wshadow t.cpp
$。 /t.exe
调用barney :: barney()
调用foo :: operator()()
调用barney :: barney()
但是它完全无法在MSVC ++上编译:
$ cl / EHsc t.cpp
Microsoft(R)32位C / C ++优化编译器版本15.00.30729.01 for 80x86
版权所有(C)Microsoft Corporation。版权所有。
t.cpp
t.cpp(17):错误C2380:'fred'(带返回类型的构造函数或当前类名的非法重定义)之前的类型b $ b t.cpp(17):error C2208:'fred':没有成员使用此类型定义
更重要的是,当它编译时,输出不是我想要的。
这是:
#include< iostream>
using :: std :: cerr;
struct fred;
struct foo {
inline fred operator()();
};
struct barney {
barney():v_(0){cerr< calling barney :: barney()\\\
; }
int v_;
};
struct fred:public barney {
foo fred;
int joe;
struct fred memfunc(){return fred(); }
};
inline fred foo :: operator()()
{
cerr<< 调用foo :: operator()()\\\
; return fred();
}
int main(int argc,const char * argv [])
{
fred f;
f.memfunc();
return 0;
}
它输出:
调用barney :: barney()
调用foo :: operator()()
调用barney :: barney()
但我会期望这样:
调用barney :: barney()
调用barney :: barney()
我得到我的输出吗?这是标准行为吗?如果是,为什么标准的哪些部分是相关的?
除了接受的答案, David Rodriguez 提供了良好的答案详细说明了在标准中我可以声明的成员名为
fred
的因为在
fred
/ code>结构你有一个
fred
(类型 foo
)的成员, c $ c> struct fred 。当你这样做: return fred
... fred
对象类型 foo
而不是 fred
结构类型,因此 foo $请注意,名称fred指的是两个不同的东西 - 类型foo的成员,以及<$ c>()的成员。
$ b < $ c> fred 结构类型。编译器必须选择一个或另一个,并且它根据C ++标准的第3.4节(名称查找)中定义的规则这样做。
fred
使用命名空间限定来引用类型:
:fred();
Here is a program that compiles without warning on e.g. GNU C++:
$ g++ -o t -Wall -pedantic -Wshadow t.cpp
$ ./t.exe
Calling barney::barney()
Calling foo::operator()()
Calling barney::barney()
But it completely fails to compile on MSVC++:
$ cl /EHsc t.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
t.cpp
t.cpp(17) : error C2380: type(s) preceding 'fred' (constructor with return type, or illegal redefinition of current class-name?)
t.cpp(17) : error C2208: 'fred' : no members defined using this type
What's more, when it does compile, the output is not what I'd expect. Can someone shed some light on what would be the required standard behaviour for this code?
Here it is:
#include <iostream>
using ::std::cerr;
struct fred;
struct foo {
inline fred operator ()();
};
struct barney {
barney() : v_(0) { cerr << "Calling barney::barney()\n"; }
int v_;
};
struct fred : public barney {
foo fred;
int joe;
struct fred memfunc() { return fred(); }
};
inline fred foo::operator ()()
{
cerr << "Calling foo::operator()()\n"; return fred();
}
int main(int argc, const char *argv[])
{
fred f;
f.memfunc();
return 0;
}
It outputs this:
Calling barney::barney()
Calling foo::operator()()
Calling barney::barney()
But I would expect this:
Calling barney::barney()
Calling barney::barney()
Why do I get the output I do? Is this standard behavior? If it is, why, which sections of the standard are relevant?
In addition to the accepted answer, David Rodriguez gave an excellent answer detailing where it says in the standard that I'm allowed to declare the member named fred
of struct fred
.
Because in the fred
structure you have a member fred
(of type foo
) which shadows the definition of struct fred
. When you then do:
return fred();
... the fred
refers to the object of type foo
rather than the fred
struct type, and so the foo
() operator is called.
Notice that the name "fred" refers to two different things - the member, of type foo, and the fred
struct type. The compiler must choose one or the other, and it does so according to the rules defined in section 3.4 ("Name Lookup") of the C++ standard.
You can force fred
to refer to the type using a namespace qualification:
return ::fred();
这篇关于为什么这个程序调用operator()而不是构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!