How is this possible to use in c++?

2019-04-18 23:08发布

问题:

  1. To my surprise, I found that the name of a c++ object can be the same as class name. Can someone explain to me the reason why?
  2. When I declare an object of class a as a a1(), it does not raise an error, but doesn't call the constructor. Why is this happening?

My code:

#include<iostream>
using namespace std;

class a 
{
    public:
    a() 
    {
        cout << "in a\n";
    }
};

int main()
{
    a a1();
    a a;
}

回答1:

When you write a a1(); it is actually being parsed as a function declaration not a call to the default constructor.

a a1;

will call the default constructor correctly

When you write a a; it works because the variable name takes preference over the class name in what is called name hiding, but even though it works it will only lead to confusion and I would avoid doing it.

And for all those people who like standards quotes here you go

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. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.



回答2:

a a1(); is a function declaration.

That's an important reason for the creation of uniform initialization in C++11. To initialize the object using the constructor in C++11, use a a1{};



回答3:

It is valid to hide the name of a class with a variable in fact if you look at the C++draft standard section 3.3.10 Name hiding paragraph 2 says(emphasis mine):

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. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.

I don't think it is good practice and it would lead to hard to maintain code. This line of code is actually declaring a function:

a a1();

you can alternatively use this pre-C++11:

a a1 ;

or uniform initialization introduced in C++11 :

a a1{} ;

Circling back to name hiding, I was pleasantly surprised to see that clang will warn you about this with this code regardless of the warning levels set:

int main()
{
   a a;
   a a2 ;
}

I receive this message:

main.cpp:12:10: note: class 'a' is hidden by a non-type declaration of 'a' here
   a a;
     ^

although I can't see to obtain a similar warning from gcc.

Update

Thinking about this comments I made earlier on warts of uniform initialization, I realized that had you suspected that a1 was somehow not the correct type you could have have used typeid to debug what was going on. For example this code:

std::cout << typeid(a).name() << std::endl ;
std::cout << typeid(a1).name() << std::endl ;

results in this output on Coliru live example:

1a
F1avE

and passing it through c++filt you receive this output:

a ()     // A function that returns type a
a        // type a


回答4:

a a1(); is a function declaration return type as a which has nothing to do with the calling constructor

a a ; is simple statement works fine will call the constructor



回答5:

This is what I got from your code when tried to compile it with clang, I think it says everything.

test.cpp:15:9: warning: empty parentheses interpreted as a function declaration
      [-Wvexing-parse]
    a a1();
        ^~
test.cpp:15:9: note: remove parentheses to declare a variable
    a a1();
        ^~
1 warning generated.