31

My question is simple. When do we need to have a default constructor? Please refer to the code below:

class Shape
{
    int k;

public:
    Shape(int n) : k(n) {}
    ~Shape() {}
};

class Rect : public Shape
{
    int l;

public:
    Rect(int n): l(n)
    {}      //error C2512: 'Shape' : no appropriate default constructor available

    ~Rect() {}
};
  1. Why is the compiler not generating the zero argument default constructor implicitly in the class Rect?

  2. As per my knowledge, if a class (Rect) is derived from another class (Shape) that has default constructor (either implicitly generated or explicitly provided), the default constructor should be generated by the compiler.

Jeffrey Bosboom
  • 13,313
  • 16
  • 79
  • 92
XMarshall
  • 953
  • 3
  • 11
  • 23
  • Where is the part where you construct the Rect object and use it? Probably you create it like 'Rect rec;' which needs a default contructor. – RvdK Mar 31 '11 at 11:17
  • 2
    IIRC if you don't specify a contructor the compiler will create a default one for you. But if you specify one it will only have that one. – RvdK Mar 31 '11 at 11:19
  • ctor == constructor ... ahhhh! – das_weezul Mar 31 '11 at 11:20
  • @poweroy: Yes you are right; but I was assuming that 'Rect rec' would use the default ctor supplied by the compiler – XMarshall Mar 31 '11 at 11:22
  • @Tomalak: I wondered wat ctor means and found out (by googling) that it is a common abbreviation for constructor. I didn't know that. – das_weezul Mar 31 '11 at 11:25

7 Answers7

34

A default constructor is not synthesised if you created your own constructor with arguments. Since you gave Shape a constructor of your own, you'd have to explicitly write out a default Shape constructor now:

class Shape
{
      int k;

  public:
      Shape() : k(0) {}
      Shape(int n) : k(n) {}
      ~Shape() {}
};

(You can leave out the empty ~Rect() {} definitions, as these will be synthesised.)

However, it looks to me like you don't want a default constructor for Shape here. Have Rect construct the Shape base properly:

class Shape
{
      int area; // I've had to guess at what this member means. What is "k"?!

  public:
      Shape(const int area)
         : area(area)
      {}
};

class Rect : public Shape
{
     int l;
     int w;

  public:
     Rect(const int l, const int w)
        : Shape(l*w)
        , l(l)
        , w(w)
     {}
};

Also note that this example is oft cited as an abuse of OO. Consider whether you really need inheritance here.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • So, if we have a `parameterized ctor` then we **must/have to** explicitly create a `default constructor`. Any reason for why doesn't the compiler `implicitly` create one for us this time? – asn Oct 07 '19 at 11:58
  • 1
    @Jos You don't _have_ to create a default constructor, if you don't want one. But if you _do_ want one, you'll have to provide it yourself (or make it `= default`). Why? Probably because if you want a non-default constructor, it's less likely that a default constructor makes sense for that class, and it would be easy for people not to realise that one was generated anyway, causing a risk of bugs. And that's exactly the case in the example above. BTW please do not use code formatting for English phrases. – Lightness Races in Orbit Oct 07 '19 at 12:00
13

A default constructor will only be automatically generated by the compiler if no other constructors are defined. Regardless of any inheritance.

And also you need to construct your base class by calling:

Rect( int n ) : Shape( n ), l(n)
{
}
Nick
  • 25,026
  • 7
  • 51
  • 83
3

The compiler will define a default ctor if and only if you don't explicitly declare any ctors.

Note that what's important is declaring the constructor, not necessarily defining it. It's fairly common, for example, to declare a private ctor, and never define it, to prevent the compiler from implicitly defining any others.

Edit: Also note that C++11 has an =default syntax for dealing with situations like yours.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • >to declare a private ctor, and never define it, to prevent the compiler from implicitly defining any others. Can you explain with an example? – Phalgun Sep 10 '18 at 19:27
  • 1
    @Phalgun: I suppose I could, but I hesitate to do so--C++11 added an `= delete;` syntax that's normally preferred in new code: `class foo { int foo() = delete; };` will prevent the compiler from defining a default ctor for `foo`. You can get the same effect by declaring a private ctor, but the `= delete;` syntax expresses the intent more directly, so I'd advise using it unless you really need compatibility with old (pre-c++11) compilers. – Jerry Coffin Sep 10 '18 at 19:34
  • If I provide a parameterized constructor in the class, that prevents the compiler from defining a default constructor. In such case, would the compiler still provide implicit copy constructor and copy assignment constructor as it would have in case I had not provided any constructor at all? – Phalgun Sep 10 '18 at 19:54
  • 1
    @Phalgun: That's correct--defining a default constructor does not affect whether a copy ctor and/or copy assignment operator will be implicitly declared. – Jerry Coffin Sep 10 '18 at 20:52
2

See this for the full behaviors of C++ WRT constructors: http://en.wikipedia.org/wiki/Default_constructor

The simple answer is that if you specify a constructor, the compiler will not create a default one for you.

This rule applies to Java as well.

Mike Thomsen
  • 36,828
  • 10
  • 60
  • 83
1

Compiler generates default constructor in case when you have not define any constructor. But if you have defined any constructor that takes some argument or not. The compiler will use that constructor and will not generate default constructor with zero argument.

Sarfraz Ahmed
  • 1,349
  • 6
  • 23
  • 43
0

The default constructor is generated only if you have not defined any other constructors.

Supposedly, if you need some special initialization in the class, the default constructor would not do the right thing.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
0

As you defined a Constructor for Shape expecting an integer you have overwritten the default constructor by doing so. So if you extend Shape you must pass an integer value to the superclass.

das_weezul
  • 6,082
  • 2
  • 28
  • 33