Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a derived class object contain a base class object?

Consider the following sample code below:

#include <iostream>

using namespace std;

class base
{
   public:
      base()
      {
         cout << "ctor in base class\n";
      }
};

class derived1 : public base
{
   public:
      derived1()
      {
         cout <<"ctor in derived class\n";
      }
};

int main()
{
   derived1 d1obj;
   return 0;
}

Questions

  1. When d1obj is created, the constructors are invoked in the order of derivation : base class constructor is called first and then the derived class constructor. Is this done because of the following reason : In-order to construct the derived class object the base class object needs to be constructed first?

  2. Does d1obj contains a base class object ?

I am adding one more question

3) When d1obj is created, the control first reaches the base class constructor and then it goes to the derived class constructor? Or is it the other way round : It first reaches the derived class constructor, finds that it has base class and so the control goes to the constructor in base class?

like image 632
nitin_cherian Avatar asked Dec 28 '22 09:12

nitin_cherian


1 Answers

1) Yes, bases are constructed first, then non-static data members, then the constructor of the derived class is called. The reason is so that the code in the constructor of this class can see and use a fully-constructed base.

2) Yes. You can take this entirely literally: within the memory assigned to the derived class object, there is a region called the "base class sub-object". A derived class object "contains" a base class subobject in precisely the same way that it contains member subobjects for any non-static data members. Actually though, the example given in the question happens to be a special case: the "empty base class optimization". This base class subobject is permitted to be size zero, even though complete objects of type base are never size zero.

This containment is a low-level thing, though. It's true as others say that conceptually bases are different from members, and the syntax and semantics of the language treat them differently even though the sub-objects themselves are all just parts of the layout of the class.

3) This is an implementation detail. The code in the body of the base class constructor is executed before the code in the body of the derived class constructor, and in effect the derived class constructor is then executed in an invisible compiler-generated try/catch block to ensure that if it throws, the base class is destructed. But it's up to the compiler how to achieve this in terms of what the function entry points in the emitted code actually do.

When a class has virtual bases it's common for a constructor to result in two different function bodies being emitted - one for use when this class is the most derived type, and one for use when this class is itself a base class. The reason is that virtual base classes are constructed by the most-derived class, to ensure that when they're shared they're only constructed once. So the first version of the constructor will call all base class constructors, whereas the second version will only call constructors for non-virtual bases.

The compiler always "knows" what bases the class has, because you can only construct an object of a complete type, which implies the compiler can see the class definition, and that specifies the bases. So there's no question of only "finding that it has a base class" when the constructor is entered - the compiler knows that it has a base class, and if the call to the base class constructor is located inside the derived class constructor code, that's just for the convenience of the compiler. It could emit the calls to the base class constructors at every place you construct an object, and for that matter in cases where the derived class constructor can be and is inlined, that's the final effect.

like image 174
Steve Jessop Avatar answered Feb 03 '23 17:02

Steve Jessop