Jump to content

  • Log In with Google      Sign In   
  • Create Account


c++ polymorphisam deleting a object, constructor concearn


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
4 replies to this topic

#1 BaneTrapper   Members   -  Reputation: 1121

Like
0Likes
Like

Posted 30 August 2013 - 12:52 PM

Hello.

I was just doing a sketch of polymorphism for my project and i came to a following situation that made me think.

If i have base and derived classes, i declare a pointer to base class and set it to (new derived class) and then call delete base class object i made.

The deconstructor for base class is called? and the object is holding derived class!

Thus making memory leak? or em i missing something;

class Base
{
public:
    Base(){}
    int q;
};

class Derived : public Base
{
public:
    Derived(){}
    int q,w;
};

int main()
{
    Base * one;
    one = new Derived;
    delete one;
    return 0;
}

Here a leak of one int size will occur?

If so, how would the base class know to call its pointing to deconstructor?


Current projects:
The Wanderer, 2d turn based rpg style game

www.gamedev.net/topic/641117-check-up-the-wanderer/


Sponsor:

#2 Brother Bob   Moderators   -  Reputation: 7787

Like
1Likes
Like

Posted 30 August 2013 - 01:02 PM

You need a virtual function (the destructor in this case) for runtime dynamic dispatch to happen. Without virtual, you get static dispatch, which is based on the static type of the object you use. In this case, the static type of the pointer is Base *, so that's the type determining which destructor is called.



#3 fastcall22   Crossbones+   -  Reputation: 4032

Like
1Likes
Like

Posted 30 August 2013 - 01:12 PM

Here a leak of one int size will occur?

No.

If so, how would the base class know to call its pointing to deconstructor?

Make the base class destructor virtual.


In C++, it is considered good practice to use a virtual destructor:
class Base {
public:
    virtual ~Base() {
    }

private:
    bool mTest;
};

class Derived : public Base {
public:
    Derived() {
        mData = new int[1000];
    }

    ~Derived() {
        delete[] mData;
    }

private:
    int* mData;
    double mOtherData;
};

int main() {
    Base* p = new Derived;
    delete p;
}
If Base::~Base were not virtual, then Derived::~Derived would not be called, and the memory for its mData would not be released. The members for Derived (the pointer mData, mOtherData, and mTest) would not leak in either case, because the members reside inside the memory block allocated for Derived. Your C++ runtime and operating system keep track of allocated blocks, so the runtime/operating system is smart enough to know the size of a block given only the pointer to its address. You can technically do something like this:
void magic( void* ptr ) {
    // Neither ~Base() or ~Derived() will be called because we won't know what type ptr is!
    // But the memory block will be freed regardless.
    delete ptr;
}

int main() {
    magic( (void*)(new Derived) );
}
Whether it is morally acceptable to do or not is another question...

Edited by fastcall22, 30 August 2013 - 01:13 PM.

c3RhdGljIGNoYXIgeW91cl9tb21bMVVMTCA8PCA2NF07CnNwcmludGYoeW91cl9tb20sICJpcyBmYXQiKTs=

#4 BaneTrapper   Members   -  Reputation: 1121

Like
0Likes
Like

Posted 30 August 2013 - 01:58 PM


void magic( void* ptr ) {
    // Neither ~Base() or ~Derived() will be called because we won't know what type ptr is!
    // But the memory block will be freed regardless.
    delete ptr;
}

int main() {
    magic( (void*)(new Derived) );
}
Whether it is morally acceptable to do or not is another question...

 

The question now is, the memory block will be freed at end of runtime of the application, or at end of scope?

It seems i do not understand the clogs beneath as i thought i did.

Thank you on your help, i appreciate it.


Current projects:
The Wanderer, 2d turn based rpg style game

www.gamedev.net/topic/641117-check-up-the-wanderer/


#5 Serapth   Crossbones+   -  Reputation: 5183

Like
0Likes
Like

Posted 30 August 2013 - 02:11 PM

 


void magic( void* ptr ) {
    // Neither ~Base() or ~Derived() will be called because we won't know what type ptr is!
    // But the memory block will be freed regardless.
    delete ptr;
}

int main() {
    magic( (void*)(new Derived) );
}
Whether it is morally acceptable to do or not is another question...

 

The question now is, the memory block will be freed at end of runtime of the application, or at end of scope?

It seems i do not understand the clogs beneath as i thought i did.

Thank you on your help, i appreciate it.

 

 

The memory is freed as soon as delete is called.  Or more accurately, the destructors are called the minute delete is called.  On the other hand, going out of scope will also result in a destructor being called if you are dealing with a non-pointer type, which is the principal a smart pointer works under ( it's a heap based object holding a stack based pointer, so when it goes out of scope, it's destructor decides what to do with the pointer it holds ).  You should really look into the idiom Resource Acquisition is Initialization, which is more or less the established norm for dealing with dynamic memory in C++.  It will take away a great many of the memory leak gotchas that C++ is prone for.  The virtual destructor thing though... that's just a wart on the language.

 

 

As to what order constructors/destructors are called, objects are constructed from the base class up.  Being the base class constructor gets called, then any derived classes get constructed.  In the event of a virtual destructor, it is exactly the opposite, so the destructor of the derived class gets called first, then the base classes destructor gets called.  If you forget to make a class destructor virtual, it will not be called at all, resulting in a leak.  In the case of multiple inheritance, it's a bit more tricky, I believe its done by the order classes are inherited ( as in  class A : B, C {} ) will call B's constructor  first, then C's, then when destructors are called, it will call first C, then B, then A.


Edited by Serapth, 30 August 2013 - 02:14 PM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS