-3
#include <iostream>
#include <string>
class MyClass{
public:
    MyClass(){
        std::cout << "Called Constructer A \n";
    }
    MyClass(int n){
        std::cout << "Called Constructer B \n";
    }
};
int main(){
    MyClass a(); //It's not works as expect
    MyClass b(0); //But this works
    MyClass c;
    MyClass d = MyClass();
    MyClass e = MyClass(0);

}

So how does e differ from b, and why b works but not a.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
cdxf
  • 5,501
  • 11
  • 50
  • 65
  • 7
    Probably a duplicate of a few questions – CashCow Oct 02 '14 at 12:18
  • Great - Not only you require an answer but for us to write the question! – Ed Heal Oct 02 '14 at 12:20
  • 2
    See http://stackoverflow.com/q/24953658/981959 and [tag:most-vexing-parse]. Please search before creating new questions – Jonathan Wakely Oct 02 '14 at 12:23
  • 1
    @EdHeal: It is not a request, because of my limited English, I am not able to write a formal question, so I just hope someone to edit my question to benefit other people. – cdxf Oct 02 '14 at 12:32

1 Answers1

2

a is declared as a function that returns a MyClass

b is the normal way to construct with an int parameter

c is the normal way to construct with no parameters

d requires an accessible copy (/move)-constructor as technically it copies the temporary on the RHS into d but the compiler might not actually invoke it.

e is the same but uses the int constructor. If you did

MyClass e = 0;

that would also require for the constructor that takes an int to be non-explicit.

To answer the question "How does e differ from b". The two objects are alike, but the construction you use with e would fail to compile if your class did not have an accessible copy/move constructor. (Move constructor in C++11)

b does not appear to declare a function so doesn't fail unlike a.

In C++03 if you put in

class MyClass {

     // etc.
  private:
      MyClass( const MyClass& );
};

The compiler would complain on the lines that create d and e

In C++11

 class MyClass {
      // etc.

      // this can be public too
      MyClass( MyClass&& ) = delete;
 };

would invoke a compiler error "use of deleted function" when you try to create d and e. The private copy constructor would also yield the error unless you did:

class MyClass{
public:
    MyClass(){
        std::cout << "Called Constructer A \n";
    }
    MyClass(int n){
        std::cout << "Called Constructer B \n";
    }

    MyClass( MyClass const&) = delete; // cannot copy
    MyClass( MyClass && ) = default; // but you CAN move

};

Now your code will compile.

Whilst we are on the subject of constructors in C++11, you can also have:

   MyClass f{}; // not a function
   MyClass g{1};
   MyClass h = MyClass{};
   MyClass i = MyClass{0};
   MyClass j = {};
   MyClass k = {0};

Note that if I change my move constructor (currently =default) to

       MyClass( MyClass && ) 
      { 
          std::cout << "Moved\n";
      }    

I tried it and "Moved" never printed. The compiler can (and did) optimise it away. But it has to be accessible.

CashCow
  • 30,981
  • 5
  • 61
  • 92