virtual and class inherience

Started by
11 comments, last by Bregma 10 years, 7 months ago

Hello there dear forum.

So my question is about class inheriences and virtual functions.

so lets say I got a class structure as following


class A{

A();
~A();

virtual void f(){ //does w/e }

};

class B : public A{

B();
~B();
void f(){ //does something diffrent }
};

main(){

B object;
}

so first thing is, in what order do constructers/deconstructers get called :o ? As far as I understand the constructurs are builed from the base up meaning the constructor of A will get called and then the constructor of B and deconstructers are the opposite, meaning B's deconstructor first and then A's. Am I right o.o ?

The main question tho once I "overload" the virtual function in the child class does the base's class function still get called or only the function in B. ( once I actually call the function ofc).

P.S all under the asumption I am creating only a object of B and no objects of A are used.

Thanks in advance ^^ <3

Advertisement

Think of it like a stack of plates. Say you have plates, A, B and C.

As they are constructed, they are made into a stack. So A, then B, then C.

Now as you remove them ( destructor ) from the stack of plates, the destructors are called in reverse order, so C, then B, then A.

So, constructors are called from the base class and up the inheritance tree. Destructors are called in reverse order, from the most inherited up to the base.

In the event of multiple inheritance, the order they are declared determines order.

so say:

class C : public A, B {}

A's constructor, then B's are called, while during destruction, B's is called first, then A.

Remember to mark all destructors as virtual or the base class destructors will not be called.

Remember to mark all destructors as virtual or the base class destructors will not be called.

That's not quite right. The destructors for any base classes will always be called as part of a derived class' destructor. What you are thinking about is deleting a derived class through a base class pointer. If the destructor is not virtual in that case what will happen is the derived class destructor will not be called, but the base class destructor will be (as well as possibly an incorrect size being passed to the memory deallocation function).

Regarding the bodies of virtual functions: Under normal circumstances, if B overrides a virtual function in A, then only the body of B's version will be run unless you explicitly call A's version. However, if you call the virtual function inside A's constructor or destructor then A's version will be called.

Remember to mark all destructors as virtual or the base class destructors will not be called.

That's not quite right. The destructors for any base classes will always be called as part of a derived class' destructor. What you are thinking about is deleting a derived class through a base class pointer. If the destructor is not virtual in that case what will happen is the derived class destructor will not be called, but the base class destructor will be (as well as possibly an incorrect size being passed to the memory deallocation function).

Yes, my bad, I should have been more explicit. The first part I hold true though, if you have a class that will ever be derived from, you should mark the destructor as virtual. I should have said may not be called however, or gone into more detail.

Thanks alot for the answer guys really cleared thigns up they were really helpful :o !

Now I just have 1 follow up question, if I dont overide the virtual f() function in my child class, can I still call the original f() function ( defined in the base class ) through my child object ( the B object in my example )

Yes, you can still call it even if a derived class doesn't override it.

As soon as you mark a method virtual in C++ it will stay virtual from that point onwards, a destructor is just another method as virtual is concerned. You shouldn't ever call virtual functions in a constructor or destructor as the dispatch might not be correct for what you want it to do.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

You can make a non-virtual call from within a virtual function though which is sometimes needed (not for destructors though, which automatically call the base class destructors)

e.g.


class Base
{
public:
    virtual void f() { cout << "Base::f" << endl; }
};

class Derived : public Base
{
public:
    void f() // is still virtual
    {
        cout << "Derived::f" << endl;
        Base::f();  // call base class implementation from derived class explicitly
    }
};
"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

You can make a non-virtual call from within a virtual function though which is sometimes needed (not for destructors though, which automatically call the base class destructors)

e.g.


class Base
{
public:
    virtual void f() { cout << "Base::f" << endl; }
};

class Derived : public Base
{
public:
    void f() // is still virtual
    {
        cout << "Derived::f" << endl;
        Base::f();  // call base class implementation from derived class explicitly
    }
};

That was hell of useful as well, thanks so much for the tip :o !

You shouldn't ever call virtual functions in a constructor or destructor as the dispatch might not be correct for what you want it to do.

Unless, of course, static dispatch is what you want it to do. It's simple enough to understand that constructors and destructors treat all calls to their own member functions as non-virtual.

For the curious, here's why: To help ensure that member functions are only being called on initialized objects in valid states, C++ has a guiding principle that no class member function should be called before the constructor of the class is called or after the destructor of the class has run.

During execution of a base class constructor, the derived class constructor has not yet been called, and during execution of a base class destructor, the derived class destructor has already been run. So it would be a violation of the above principle if the base class constructor or destructor could call any derived class members.

Virtual function calls would allow exactly that, so within constructors and destructors, calls to the object's member functions are all treated as non-virtual.

The way I like to think of it is that during execution of a base class constructor, the object being constructed is not yet a derived type object. The derived class's constructor has not yet been called and so the derived class's functions are not yet accessible. Similarly, during execution of a base class destructor, the object being destructed is no longer a derived type object. The derived class's destructor has already run and so the derived class's functions are no longer accessible.

This topic is closed to new replies.

Advertisement