0
votes

I am a bit confused, i was reading this C++ Constructor/Destructor inheritance, and so it says constructors and destructors are not inherited from the base class to the derived class but the constructors and destructors are called when i create a derived object. So is the constructors and destructors of the base class data members of the inherited classes?

2
Constructors/destructors are not data members. The chosen answer on the SO link you provide explicitly answers that question.OldProgrammer

2 Answers

4
votes

Constructors and destructors are very special animals; in fact, the Standard identifies them as "Special Member Functions."

All the things that are weird and unique about constructors and destructors (for example, the fact that they don't have "names" and the fact that they aren't "inherited") is really quite irrelevant to almost all programming and programmers. Here is what you need to know:


Constructors and destructors are not member variables (obviously) -- they are (special) member functions.


When you derive from a base class, some constructor of the base class is going to be called. Which constructor depends on how you've written your code. If you don't explicitly specify which constructor to call, the default constructor will be called. This happens in your derived object's initialization list, even if you haven't written one.

You may specify another constructor through an initialization list, only:

class Bar : public Foo
{
public:
  Bar()
  :
    Foo (1, 2, 3)
  { 
  }
};

Here, Bar's initialization list specifies a constructor on Foo which takes 3 parameters convertible from integrals. One such constructor might be:

class Foo
{
public:
  Foo (int a, long b, unsigned c)
  :
    mA (a),
    mB (b),
    mC (c)
  {
  }
private:
  int mA;
  long mB;
  unsigned mC;
};

Back to the Bar example above. By the time the initialization list is done executing, and before the body of Bar's constructor starts, all of Bar's base classes and member variables have already been instantiated and initialized. This is why the only way to specify some constructor for Foo other than the default constructor is through an initialization list -- which, in turn, is why you must have an initialization list if the base class has no default constructor available.


Question: If constructors and destructors are not inherited, then why are they called when instantiating a derived type?

Answer: Because constructors are what initialize objects, and a derived type has an IS-A relationship with the base type.

Consider Foo and Bar above again. Bar derives from Foo, so in a sense Bar IS A Bar. It's more than just a Foo, it's got stuff that Foo doesn't have; but it has all the Foo-ness. Since a Bar object is in part a Foo, that Foo-ness has to be initialized. Since all initialization ob objects is done through a constructor, Foo's constructor must be called.

So, constructors and destructors aren't inherited in the sense of overloading -- but the constructors of the base class will be called. They have to be. Otherwise the Fooness of a Bar object could never come to be.


When you are deriving from a base class, something that you will often want to do is pass around a pointer to the base class. In fact, you may not need a pointer to the derived type at all in many cases. This is especially true when designing abstract interfaces.

There is a nasty problem that can come up when you do this and haven't taken all the needed preperations. Consider:

class Foo
{
public:
  std::string mS;
};

class Bar : public Foo
{
public:
  long mArray[0xFFFF]; // an array of 65K longs
};

int main()
{
  Foo* thingy = new Bar;  // Totally OK
  // ... do stuff...
  delete thingy;  //  WHOOPS!  Memory leak!
}

Above in the delete call we're deleting through a base class pointer. The Foo destructor (which is implicit) is properly called, but the Bar destructor is not -- leaving that huge array of 65K longs leaked.

To fix this, we need to give Foo a virtual destructor:

class Foo
{
public:
  std::string mS;
  virtual ~Foo() {}
};

This doesn't do much, but it does one critical thing: it sets up polymorphism so that when we call the destructor (implicitly), the virtual override will get called.

This is a critical step when designing a class hierarchy. If you think there is any chance that people will pass around pointers to the base class, you should have a virtual destructor in the base class. In fact, I would suggest that in almost every case you should have a virtual destructor even if you don't think people will use it this way.

3
votes

No. As you said, constructors and destructors are not inherited (by the way, the assignment operator isn't either). It would be logically flawed if they were inherited, right? Constructors (and destructors) are specific for that exact class; and since the derived class usually has something specific and new, the base constructor is not enough to initialize the inherited class objects.

So why is the base constructor called when creating an object of the child class? Well, every derived object has a sub-object - which is the actual object of the parent class (I hope this sentence wasn't difficult to understand).

The compiler will:

1) locate the constructor of the derived class whose list of initializers best fits the arguments passed, but not execute it;

2) execute the constructor of the base class to create the sub-object;

3) execute the constructor of the derived class, to create the actual object.

I hope this is clear; you can find a much more detailed explanation in the answer above :)