Does pointer to derived class create the Base class first or not?

246 views Asked by At

I have the following code

#include <iostream>
using namespace std;

class B{
    int i;
    public:
    B(){
        cout << "Constructing B\n";
    }
    void print(){
        cout << "Printing from B with size : "<<sizeof(*this)<<endl;
    }
};



class D:public B{
    int i;
    public:
    D(){
        cout << "Constructing D\n";
    }
    void print(){
        cout << "Printing from D with size : "<<sizeof(*this)<<endl;
    }
};


int main(){

    B b;
    b.print();
    D d;
    d.print();

    D* dp;
    dp->print();
}

Which gives me following output:

Constructing B
Printing from B with size : 4
Constructing B
Constructing D
Printing from D with size : 8
Printing from D with size : 8

So is it true that while you create a pointer to derived class it doesn't create the instance of a base class first? I don't think its true though because the size of D class is the proof. But its not even calling the base class constructor. Can anyone explain this?

4

There are 4 answers

0
Jerry Coffin On BEST ANSWER

Right now your pointer isn't be initialized at all, so trying to use it gives undefined behavior. Try something like:

D *dp = new D; 
dp->print();
delete dp;

Or to do it better, something like:

std::unique_ptr<D> dp = std::make_unique<D>();
dp->print();

...and the unique_ptr will automatically delete the D when it goes out of scope.

Note, however, that you've define print as a non-virtual function, so the function that's invoked will depend on the type of pointer (or reference) used, not the type of the object it refers to. In addition, you haven't defined a virtual dtor.

Therefore, if you were to do something like:

B *p = std::make_unique<D>();
p->print(); // would invoke B::print, even though the object is a D

...and when it went out of scope, it would be destroyed incorrectly so you'd get undefined behavior. To correct this, you want to change B to something like this:

class B{
    int i;
    public:
    B(){
        cout << "Constructing B\n";
    }
    virtual void print(){
        cout << "Printing from B with size : "<<sizeof(*this)<<endl;
    }
    virtual ~B() = default;
};

When you do this, the answer is "yes"--when you create the derived object, it'll first invoke the ctor for the base class, then the ctor for the derived class. When the derived object is destroyed, that is reversed: first the dtor for the derived class will be invoked, then when it finishes the dtor for the base class will execute.

0
AnT stands with Russia On

Pointers do not create anything. Pointers are just pointers - scalar objects that contain addresses. It is your responsibility to make your pointers to point to proper locations in memory.

In your example pointer dp is not initialized. You never made it to point anywhere, so it points nowhere. Your attempt to call dp->print() produces undefined behavior. End of story.

0
Alexandre Severino On

You can assign a pointer of Base with a Derived object by using the powerful polymorphism. That is possible because Derived implements everything that Base contains. Thus, it is implicit that Derived underlying instantiates the Base during its own instantiation.

class Base
{
public:
    Base()
    {}
}

class Derived : public Base
{
public:
    Derived()
    {}
}

Derived *derived = new Derived();
Base *base = derived;
0
phantom On

It is constructing the base class before the derived class. Your output reflects this. Look at this

//Constructs Base class
Constructing B
//Constructs Derived class
Constructing D
//Prints from derived
Printing from D with size : 8

The reason that your code prints Printing from D with size : 8 twice without calling the constructor is that your code never creates a second instance of D.

D* d;
^^^^ Declares a pointer to a D, Does not create a D!

When you call d->print(); it is undefined behavior as d does not point to an instance of D. Finally, your code prints a value determined at compile time (sizeof(D) is a compile time value) and does not touch the this pointer your code runs.

See the documentation for sizeof here.