开发者

Defaults constructors, why my class seems to have three? When compilers treats classes like structures?

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?

  • 开发者_C百科

[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.


I decided to check what will happen after changing struct to class.

The only difference between struct and class is default visibility of members and default inheritance mode. struct D : B { ... is equivalent to class D : public B { public: ....


Well it seems normal that "//Bar bar3(2, false, "so", 7.0);" doesn't work since you didn't define a constructor with that signature. In order for that to work you need to define a constructor with that signature in your class. The compiler only generates the default constructor and default copy constructor for you unless you declare them yourself.


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" };


With //Bar bar3(2, false, "so", 7.0); you are calling a ctor that does not exist.


Bar meets the POD type requirements, which means it can be initialized like a C structure. Being a class or a struct has no impact on this.


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

1.Yes - you are right about the above.

2.

Is it compiler's (gcc in this case) feature

What 'feature' are you talking about? Just overload your constructor to have a method Bar::Bar(int,bool,char*,double) and you're smooth sailing


It is well know that default constructor and default copy constructor exist for any class in C++ regardless if they are explicitly declared or not. I think what is happening when you use the following syntax:

Bar arr[2]={{0, true, "a", 3.14}, {1, false, "z", 42.0}}; 

Is that the compiler inferred the type of objects then call the default constructor of each object, then assign each field conformed its position in the class definition. The compiler does not could call the default copy constructor because no object of the same type is passed directly when you create the new object, this is, copy constructor should be called in the following scenarios:

Bar a;     //default constructor is called
Bar b(a);  //default copy constructor is called
Bar c = a; //default copy constructor is called

What you should do is to add the default constructors to the Bar class and then debug for knowing what really is happening...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜