c++ - Why does this program call operator () instead of the constructor? -


here program 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 fails compile on msvc++:

$ cl /ehsc t.cpp microsoft (r) 32-bit c/c++ optimizing compiler version 15.00.30729.01 80x86 copyright (c) microsoft corporation.  rights reserved.  t.cpp t.cpp(17) : error c2380: type(s) preceding 'fred' (constructor return type, or illegal redefinition of current class-name?) t.cpp(17) : error c2208: 'fred' : no members defined using type 

what's more, when compile, output not i'd expect. can shed light on required standard behaviour code?

here 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 expect this:

calling barney::barney() calling barney::barney() 

why output do? standard behavior? if is, why, sections of standard relevant?

in addition accepted answer, david rodriguez gave excellent answer detailing says in standard i'm allowed declare member named fred of struct fred.

because in fred structure have member fred (of type foo) shadows definition of struct fred. when do:

return fred(); 

... fred refers object of type foo rather fred struct type, , foo () operator called.

notice name "fred" refers 2 different things - member, of type foo, , fred struct type. compiler must choose 1 or other, , according rules defined in section 3.4 ("name lookup") of c++ standard.

you can force fred refer type using namespace qualification:

return ::fred(); 

Comments