views:

113

answers:

6

I have 2 classes Base and Derived (derived publically from Base). When I write -

Derived * d1 = new Derived;
delete d1;

Compiler sees that d1 is a Derived type object. So it calls the derived class constructor (which calls the base class constructor). I have 2 questions here -

1) Why do we follow this order?

2) How do these constructors work together to allocate memory? I need some implementation details

Now the next statement is delete d1. So compiler sees that d1 is a derived type object and so calls the destuctor of derived class (which calls the destructor of base class after deleting the derived class members). I have one question here -

1) How do these destructors work together? Lets say the derived class destructor is passed the address of d1 in memory. How do these destructors free up the space now?

+2  A: 

That code will not compile. You cannot deletean automatic instance, you must use new to allocate the instance in order to use delete on it.

When it comes to constructor order, I guess it just makes sense to run them so that more specialized classes can depend on the more general parts having already been done.

The memory layout of each class is known by the compiler, from inspecting the complete class declaration and recursing up through any and all superclasses.

unwind
+1  A: 

The code example you give wouldn't compile. delete works on pointers, not objects.

I don't think C++ itself (the language standard) says anything about how memory is used to represent instances of types that use inheritance. However, in most implementations a single chunk of memory is allocated from the free store that is large enough to hold all the data of Base and Derived. When an instance of Derived is deleted, both constructors run and then the single memory block is freed.

Similarly, if an instance of Derived is an embedded data member of some class Container, then the memory block that holds an instance of Container will be made large enough to hold Derived (and hence Base) and all the other data of Container.

Daniel Earwicker
A: 

When constructing, constructors are called from the highest base class until the oneof the most derived, which will be called the latest.

When destructors are called, it's the reverse order. First is called the destuctor of the most derived, until the one of the highest base class.

Stephane Rolland
+2  A: 

1) By default, the base class constructor is called automatically. However, the derived constructor is allowed to call the base class constructor explicitly in its initializer list. This would not be possible if the constructors were not executed derived-class-first.

Derived::Derived() : foo( 42 ), bar( 7 ), Base( 1, 2 ) { }

2) The compiler knows the memory footprint of the derived class (as all member variables are known at compile time), and allocates enough memory to hold both the base class and the derived class members. Details on the memory layout are specified by the ABI used by your system.

3) Destructors do more than just freeing up the memory. Actually, the destructors do not free up memory required to hold any member variables - only, where necessary, memory that member pointers point to.

DevSolar
+1  A: 

(1) The base class does not depend on the derived class, but the other way around is possible. I.e. a Base class cannot know which fields any Derived class has, so Base::Base won't and can't touch them. The other way around is possible, Derived::Derived can access Base::member. Therefore, Base::member is initialized by Base::Base before Derived::Derived gets the chance to useBase::member`.

(2) constructors don't allocate memory. That's new's task. Or if the object is a global, the compilers'. The constructor is called with this already pointing to the allocated memory; it need just fill in the members at that location.

In the case of a base and derived constructor, one common implementation inserts the call to the Base constructor in the generated code for the Derived constructor. With single inheritance, the Base and Derived class usually share the same this pointer, so the Derived constrcutor can then pass the same pointer that it got.

(1) [sic] Just like constructors don't allocate memory, destructors don't free it. That's the task of delete - and again, for globals the compiler would do it.

MSalters
A: 

While in inheritance, the compiler should know what it is inheriting. It should know what the Base class consists of. It cannot inherit from a class, which it doesn't have any idea.. So, it does make sense that the Base class constructor is called first and then the Derived.

And in the case of Destruction, if the Base destructor is being called first and gets destructed, the Derived class may still be using the Base class members which becomes invalid.. Hence the Destruction is the exact inverse of the construction..

liaK