26
#include <iostream>
using namespace std;

struct test
{
    test(){cout<<"class"<<endl;}
};
void test(){cout<<"function"<<endl;}

int main()
{
    test();
    return 0;
}

Output:

function  

(VS2013 ang gcc 4.8.1)

Why function is selected? Isn't it ambiguity?

Kami
  • 19,134
  • 4
  • 51
  • 63
Denis
  • 2,786
  • 1
  • 14
  • 29
  • 1
    i think the compiler picks the function because a class is never called with its base name.. if you remove the void test(), you may likely get an undefined function.... it is not ambigue because the two are always called by diffent contexts... – Leonardo Bernardini Oct 13 '14 at 14:12
  • Check this question, it is similar: http://stackoverflow.com/questions/7763802/why-cant-a-class-have-same-name-for-a-function-and-a-data-member @LeonardoBernardini You do not get undefined function if you remove void test(), because then the compiler will create a new test object but not assign it anywhere. – Cantfindname Oct 13 '14 at 14:12
  • 3
    you can reach your class with `struct test t{};` syntax – Piotr Skotnicki Oct 13 '14 at 14:16

3 Answers3

24

This is called name hiding and described in

3.3 Scope [basic.scope]

3.3.1 Declarative regions and scopes [basic.scope.declarative]

4) Given a set of declarations in a single declarative region, each of which specifies the same unqualified name,
— they shall all refer to the same entity, or all refer to functions and function templates; or
— exactly one declaration shall declare a class name or enumeration name that is not a typedef name and the other declarations shall all refer to the same variable or enumerator, or all refer to functions and function templates; in this case the class name or enumeration name is hidden (3.3.10). [...]

emphasis mine.

Note that changing the order of declaration doesn't affect the outcome:

void test(){cout<<"function"<<endl;}

struct test
{
    test(){cout<<"class"<<endl;}
};

int main()
{
    test();
    return 0;
}

still prints out function.

In case it isn't obvious, don't do this :)

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 3
    You should probably point out that this is a hack, for reasons of C compatibility, and that you probably don't want to use it in actual code. – James Kanze Oct 13 '14 at 14:43
  • 2
    You didn't know that it was for C compatibility, or you didn't know that it was a bad idea:-). The real reason it's there is to support the Posix function `stat` (which has an out parameter `struct stat*`); in C, you need the `struct`, and names after the `struct` are looked up in a different namespace than the others. The somewhat awkward rules in C++ are an attempt to support this, while still allowing the use of C libraries like Posix. (And I'm sure that this was documented in some early specifications, maybe the ARM.) – James Kanze Oct 13 '14 at 17:12
10

From N3485 §3.3.10 [basic.scope.hiding]/2:

A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope.

Therefore, the function takes precedence over the class.

As mentioned in the comments, the class is still accessible via the class or struct keyword. If the class took precedence, the function would be unreachable.

Community
  • 1
  • 1
chris
  • 60,560
  • 13
  • 143
  • 205
-5

I'm not certain either of the previous responses are the "why" for your particular instance.

Don't get me wrong; They are true and accurate.

I just think it's simpler.

In your example, you never instantiate the struct.

In other words, you declared it, but you never used it.

Since you never referenced it, it is never called.

Name precedence and such don't really apply here, since you never instantiated the struct.

Hope this helps,

-john

John
  • 97
  • 1
    You are supposed to cite any source or documentation to reason what you think, or provide any evidence to prove it correct. In this answer you failed to do so. – Krzysztof Jabłoński Oct 13 '14 at 18:13
  • 6
    That answer is not even logical in itself: The class is never instantiated *because* the precedence rules cited in the other answers require that the function is called. If the precedence rules where the other way round, a temporary object would be instantiated and the constructor would be called. So saying "precedence and such don't apply, because the struct is not instantiated" is just plain wrong. – Oguk Oct 13 '14 at 22:23