9

I happen to write a code like this:

class a
{
    public:
        a() {}
};


int main()
{
    a *a = new a;        // line 10
    a a;                 // line 11
    return 0;
}

g++ errors out:

2.c: In function ‘int main()’:
2.c:10:16: error: expected type-specifier before ‘a’
2.c:10:16: error: cannot convert ‘int*’ to ‘a*’ in initialization
2.c:10:16: error: expected ‘,’ or ‘;’ before ‘a’
2.c:11:7: error: expected ‘;’ before ‘a’

I found that, if I change "a *a" to "a *b" at line 10, then g++ is happy, here is the good code:

class a
{
    public:
        a() {}
};


int main()
{
    a *b = new a;
    a a;
    return 0;
}

I am confused, not sure why the original code does not compile and how the "fix" works.

Any idea?

my_question
  • 3,075
  • 2
  • 27
  • 44
  • 1
    If possible, then simply don't have types, variables and functions that hide names of each other. You and anyone else who reads your code (including compiler) may get confused and refuse to read it. – Öö Tiib Nov 11 '12 at 16:50
  • 1
    Don't have variables named the same as classes. It is only possible in a very limited set of circumstances, and always confusing. – n. m. could be an AI Nov 11 '12 at 17:11

4 Answers4

15

See Vaughn's answer for details. However, you can fix this problem if you specify that you want to use the class and not the variable:

class a
{
    public:
        a() {}
};


int main()
{
    a *a = new class a;
    return 0;
}

or

int main()
{
    class a a; // although the class word isn't needed here
    return 0;
}

Explanation

Back in the days of C structs were put in their own namespace. In C++ something similar happens, however, the class names are available outside of their namespace, as long as there is no local function or variable with the same name.

If you happen to use the same name for both a class/struct A and a variable/function A you have to use the struct/class keyword, because the compiler interprets all following occurrences of A as the variable/function and not the struct/class.

Community
  • 1
  • 1
Zeta
  • 103,620
  • 13
  • 194
  • 236
  • 1
    Thanks. Still puzzled to me why C++ parser cannot differentiate the case, anything after "new" must be a type, not object, so it should be "class a". Maybe this is how parser works. Anyway, thanks! – my_question Nov 11 '12 at 17:16
5

As soon as the variable name you are declaring is seen, it becomes accessible.

So in this code:

a *a = new a;
           1

At point 1, a is referring to the variable a and not the class a.

When you do this instead:

a *b = new a;
a a;

it isn't a problem, since b is a different name.

Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
1

G++ finds the identifier a and thinks you mean the pointer, not the class name. You line a *a = new a; is the same as:

a *a;
a = new a;

Here in the second line, G++ gets confused, because you have already defined a to be a pointer, not a class name.

The other line a a; works, because it is just one statement.

It is generally a good idea to give your classes CamelCase (fist letter of each word is upper case) names, and instances (variable names) lower_case or lowerCamelCase (sometimes referred to as mixedCase) names.

opatut
  • 6,708
  • 5
  • 32
  • 37
0

You can use typedef to temporarily alias the type.

class a;
typedef a _a;
_a a;
void Get(_a a);
Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
e.s. kohen
  • 213
  • 1
  • 4
  • 21