Are private base class constructors still called?

68 Views Asked by At
#include <iostream>

// first base class
class Vehicle
{
public:
    Vehicle() { std::cout << "This is a Vehicle\n"; }
};

// second base class
class FourWheeler
{
public:
    FourWheeler()
    {
        std::cout << "This is a 4 wheeler Vehicle\n";
    }
};

// sub class derived from two base classes
class Car : private Vehicle, private FourWheeler
{
};

// main function
int main()
{
    // Creating object of sub class will
    // invoke the constructor of base classes?
    Car obj;
    return 0;
}

I was expecting there to be no output but it gives output (ie. it runs the constructor of super classes). Why does this happen? Please enlighten me.

2

There are 2 best solutions below

0
Siddharth Sagar On

Private is used to describe the access control of the class. The inherited classes will run their respective constructors regardless of private or public inheritance.

Private should be used to define methods and functions you do not want to be exposed to methods and functions outside the class. It is not meant to hide or lock functions.

0
Mostafa Mohamed Farag Beshier On

Public, private, and protected keywords that are used in inheritance are called access modifiers. These change the max control level of base class's members that are inherited. Constructors are public methods that cannot be inherited, and they called only once upon creating an object. By default, the constructor of the base class is called by the constructor of the child class. If there are multiple inheritance in the same child class, their constructors called by the same sequence of inheritance. In your example:

class Car : private Vehicle, private FourWheeler
{
    // The access modifier is private for both base classes.So, all the public and protected inherited members are treated here as private members.
    // All the private members of the base classes will not be inherited to the Car class.
    // You cannot access the inherited members outside the class or when inheriting this class.
    // The constructor of Vehicle class will be called first then FourWheeler class.
    // There is no constructor in the Car class so the compiler will generate it by default constructor.
    // It also will generate the copy constructor and other functions like assignment operator and move operator by default.

};

Here the compiler will extend this class code to this.

class Car : private Vehicle, private FourWheeler
{
public:
    Car() = default; // default constructor
    Car(Car& source) = default; // copy constructor

};

The constructor will be extended like this:

class Car : private Vehicle, private FourWheeler
{
public:
    Car(){
        //default things.
    }
};

But where is the base classes' constructor call. Even if you wrote the child class's constructor like this it will be extended to call all the base classes' constructors and pass their default arguments to the call. Your class code will be extended to this:

class Car : private Vehicle, private FourWheeler
{
public:
    Car(): Vehicle(), FourWheeler(){
        //default things.
    }
};

The section after ":" is called direct initialization. direct initializations have a higher priority than the section in the curly braces. So, if there are statements in the child class constructor like this:

class Car : private Vehicle, private FourWheeler
{
public:
    Car() : Vehicle(), FourWheeler() {
        cout << "I have created a car!\n";
    }

};

This will be the output:

This is a Vehicle
This is a 4 wheeler Vehicle
I have created a car!