The default constructors, why my class seems to have three? When compilers treat classes as structures?

advertisements

I always thought, that there are only two defaults construcors: constructor with no arguments, and copy construtor.

But today I wrote something like this:

First I wanted to make sure that in C++ initialization of structures in c-style is still valid..

struct Foo{
    int a;
    bool b;
    char* c;
    double d;
};
//..
Foo arr[2]={{0, true, "a", 3.14}, {1, false, "z", 42.0}};

ok, this works. But next, I decided to check what will happen after changing struct to class.

class Bar{
 public:
    int a;
    bool b;
    char* c;
    double d;
};

//..

Bar arr[2]={{0, true, "a", 3.14}, {1, false, "z", 42.0}};//works
Bar bar;                                                 //works
Bar bar2=arr[1];                                         //works
//Bar bar3(2, false, "so", 7.0);                         //of course doesn't work
//first, second, third ways works...

this is compilable as long as class Bar doesn't have any private/protected fields (but it can contains methods). So, as long as compiler can create class which uses only simple features of structures, so long this can be compiled.

  • First question: Am I right?

  • Second question: Is it compiler's (gcc in this case) feature or this is exactly what Standard says?

[EDIT]:

code //Bar bar3(2, false, "so", 7.0); //of course doesn't work is not an issue here ;)


PS. I am still learning English, however sometimes I am making stupid mistakes. I am doing my best, writing questions and answers in English, however I would be very glad if you will edit my post in case of any mistakes. I promise, your effort will not be wasted.


Although you called it C-style initialization, its official name is initializer list. Only aggregates can be initialized with initializer lists (see 8.5 in the standard).

An aggregate is an array or a class with

  • no user-declared constructors,
  • no private or protected non-static data members,
  • no base classes,
  • and no virtual functions.

Those are the actual restrictions you have. That means you may use initializer lists with non-POD aggregates:

struct Aggregate
{
   std::string s;
};

Aggregate ag = { "hello" };