Freeing abstract class pointers - c++

In C++ I have a class A that has an abstract class pointer to allow for polymorphism contained in a class B, I have another pointer to an abstract class C that allocates a concrete instance of a child class of class B into that memory and I need to call a cleanup (see question below) function from class C to deallocate the memory taken by the child class of class B that I allocated from the heap, the problem is I can't guarantee I have access to the cleanup function because I only have a pointer to class C which I can't just copy, because it could be gone by the time I call need to destroy the containing class A.
In order to solve the problem of not having access to the cleanup function can I call delete on the class A pointer even though I'm pointing to a child class? Does C++ new also store heap block size like malloc so that you can just delete memory referenced by a pointer to an abstract class like this? If not is there another way to organize the program that allows me to handle the situation?

I'm using my crystal ball because it's hard to follow your question but you probably need virtual destructors.

The standard states (§5.3.5 ¶3):
In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.
If I understood correctly, you have an object of some derived type, and you hold a pointer to it whose static type is one of its base classes; so, you're ok, as far as you have virtual destructors.
Edit well, I was way too slow :P

Related

Memory management with pointers created using "new" in C++

I have a base class where 2 pointers are declared in the header. The pointers are then initialized with the "new" keyword in a method of the base class and deleted with "delete" in the destructor of the base class.
I also have a derived class that inherits from the base class. I declare a pointer there as well. Depending on a boolean, this pointer is assigned to either pointer of the base class. However, this results in a segfault when the destructor of the base class is called.
My understanding is that this happens because the derived class will delete the pointer automatically before the destructor of the base class is called. When "delete" is called in the base class, then this area of memory has already been freed and a segfault results.
What is the correct way of doing this? My aim is to have a pointer in the derived class that can flexibly equal one of the pointers initialized in the base class.
Either do not delete the pointer in the derived class or use standard smart pointer std::shared_ptr
Your base class should probably have a virtual destructor, then you should override the destructor in your derived class to make sure everything gets deleted in the order you expect.
But it's hard to tell what's happening without seeing the code, so that's just a thought...

Basic polymorphic pointers to base classes

While I've been working in c++ for a while, I haven't had need to use polymorphic features until now, and I'm very intrigued by them.
If I have a base class ClassA and another ClassB derives from it, I understand that I can have virtual member function in ClassA that, when implemented in ClassB, will be called in a ClassB instance even if that instance is pointed at using a ClassA pointer. Without this virtual keyword, I presume the base class implementation would prevail when using a base class pointer, yet be operating on an object that was instantiated from the subclass, which seems questionable to me if in fact ClassB has its own implementation of the same function that is effectively ignored in such a case.
Is this a correct understanding of polymorphic behavior?
Now the real question is how do you refer to ClassB using a pointer to is base class. I can really only think of two ways:
Create the pointer at the time of instantiation, using a function that returns a base class pointer while actually allocating memory for the subclass instead, using the subclass's constructor. (Does such a creation function have a common name?)
Casting an object using static_cast and assigning it to a pointer to the base class.
Are these the two main techniques for generating base class pointers to objects of a subclass?
The easiest way is to simply assign it, no cast necessary:
ClassA *ptrA = new ClassB;
You're correct that you need the virtual keyword to enable polymorphic behavior. Here's one way to think about it. C++ operates on the static type of an object. When you call ptrA->foo(), the type of the pointer is ClassA*. If that function is not declared virtual, then it will blindly call ClassA's version of the function. There's no other choice. But if foo() is virtual, then it knows to stop and ask, "Wait, what type am I really?" And the answer in that case is ClassB, so it will call ClassB's version.
Also note that you don't need pointers to achieve this. Another common way you'll see polymorphism in action is via a function call:
void bar(ClassA &aObj)
{
aObj.foo();
}
// ...
ClassB bObj;
bar(bObj);

c++ casting base class to derived class mess

If I were to create a base class called base and derived classes called derived_1, derived_2 etc... I use a collection of instances of the base class, then when I retrieved an element and tried to use it I would find that C++ thinks it's type is that of the base class, probably because I retrieved it from a std::vector of base. Which is a problem when I want to use features that only exist for the specific derived class who's type I knew this object was when I put it into the vector.
So I cast the element into the type it is supposed to be and found this wouldn't work.
(derived_3)obj_to_be_fixed;
And remembered that it's a pointer thing. After some tweaking this now worked.
*((derived_3*)&obj_to_be_fixed);
Is this right or is there for example an abc_cast() function that does it with less mess?
edit:
I had to expand this into another question, the full solutions are shown there. stackoverflow.com ... why-the-polymorphic-types-error-and-cleanup-question
If you store your objects in a std::vector<base> there is simply no way to go back to the derived class. This is because the derived part has been sliced of when storing it in an instance of base class (afterall your vector contains copies of your data, so it happily copies only the base part of your objectes), making the stored object a true instance of base class, instead of a derived class used as a base class.
If you want to store polymorphic objects in the vector make it a std::vector<base*> (or some kind of smartpointer to base, but not base itself) and use dynamic_cast<derived_3*> to cast it to the correct type (or static_cast, if its performance sensitive and you are confident enough that you are trying to cast to the correct type (in that case horrible things will happen if you are wrong, so beware)).
If you are using a vector of base then all your instances are base instances and not derived instances.
If you try to insert a derived instance, the object will be sliced. Inserting into a vector always involves a copy and the target type is determined by the type of the object that the vector holds. A vector cannot hold objects of different types.
Most of the time you shall not need to do this. A carefully designed class hierarchy can handle this by polymorphism (i.e. virtual functions).
If you really need to cast to the derived type, use dynamic_cast operator.
What you are trying to do is not even remotely possible. If the objects stored in your container have type base, then they are base, period. They are not derived objects, they will never become derived objects and they cannot be used as derived objects regardless of what you do.
Your cast through pointers is nothing than just a hack that reinterprets memory occupied by base object as derived object. This is totally meaningless and can only "work" by accident.

Derived destructor called before base destructor causes issue

Here is my issue:
My base class has a constructor that takes in a class pointer, if that pointer is NULL, it knows to instance it itself and maintain it.
The problem is, in the base destructor, I have to unregister that pointer with something private of base. So what happens is when I try to make a call to the class pointer in the base destructor and the derived is maintaining it, it has already been freed. So that causes a problem. What could I do?
Thanks
If the base class creates an instance for the pointer, why can't it free it as well? Is there anything stopping you from moving the free into the base destructor?
It's always best to be consistent in terms of who does what, at a certain level of hierarchy- splitting up the same responsibility across several levels of hierarchy will surely lead to problems such as this. Not to mention, if you want to create another class that inherits from base, you will have to re-implement this management in the new class as well, creating code duplication.
The order of constructors and destructors in inheritence is opposite; the base constructor is called before any of it's derived constructors. Upon delete, the inverse happens - the derived class is deleted first.
To solve your problem, could the base destructor not test whether its private instance is not NULL?
The base class could implement a protected member function to do the cleanup, then the derived destructor could call this helper function before destroying the resource.
From your description I gather that sometimes the derived class will be in charge of this pointer, and sometimes the base class will be. The simplest solution I can think of is to add a boolean in your base class that will allow you to track who owns the object. If the base class has initialized the pointer, set the boolean to true. Then your destructor can check who owns the object and in turn whether it should clean up.
A better solution would be to use boost:shared_ptr. This is a reference counting pointer abstraction that will automatically cleanup your object when its last reference goes out of scope. With this abstraction you generally don't need to worry about who releases your pointer.
If your constructor allocates memory, the corresponding destructor is responsible for freeing it. If you conditionally allocate memory, then you need to conditionally free it. A Boolean flag would help you determine if allocation occurred.
Another solution is to use a reference counting. At the time of the allocation the reference count shall be 1. If another class has interest in the object, it retains the pointer by increasing the reference count. If a class is no longer interested in the object, it decreases the reference count. When the counter reaches 0, the object must be deleted. shared_ptr is a standard C++ reference counted auto pointer implementation, which works very well in complex mixed ownership situations.

How are constructors and destructors implemented in C++?

I have 2 classes Base and Derived (derived publically from Base).
When I write -
Derived * d1 = new Derived;
delete d1;
Compiler sees that d1 is a Derived type object. So it calls the derived class constructor (which calls the base class constructor). I have 2 questions here -
1) Why do we follow this order?
2) How do these constructors work together to allocate memory? I need some implementation details
Now the next statement is delete d1. So compiler sees that d1 is a derived type object and so calls the destuctor of derived class (which calls the destructor of base class after deleting the derived class members). I have one question here -
1) How do these destructors work together? Lets say the derived class destructor is passed the address of d1 in memory. How do these destructors free up the space now?
That code will not compile. You cannot deletean automatic instance, you must use new to allocate the instance in order to use delete on it.
When it comes to constructor order, I guess it just makes sense to run them so that more specialized classes can depend on the more general parts having already been done.
The memory layout of each class is known by the compiler, from inspecting the complete class declaration and recursing up through any and all superclasses.
1) By default, the base class constructor is called automatically. However, the derived constructor is allowed to call the base class constructor explicitly in its initializer list. This would not be possible if the constructors were not executed derived-class-first.
Derived::Derived() : foo( 42 ), bar( 7 ), Base( 1, 2 ) { }
2) The compiler knows the memory footprint of the derived class (as all member variables are known at compile time), and allocates enough memory to hold both the base class and the derived class members. Details on the memory layout are specified by the ABI used by your system.
3) Destructors do more than just freeing up the memory. Actually, the destructors do not free up memory required to hold any member variables - only, where necessary, memory that member pointers point to.
(1) The base class does not depend on the derived class, but the other way around is possible. I.e. a Base class cannot know which fields any Derived class has, so Base::Base won't and can't touch them. The other way around is possible, Derived::Derived can access Base::member. Therefore, Base::member is initialized by Base::Base before Derived::Derived gets the chance to useBase::member`.
(2) constructors don't allocate memory. That's new's task. Or if the object is a global, the compilers'. The constructor is called with this already pointing to the allocated memory; it need just fill in the members at that location.
In the case of a base and derived constructor, one common implementation inserts the call to the Base constructor in the generated code for the Derived constructor. With single inheritance, the Base and Derived class usually share the same this pointer, so the Derived constrcutor can then pass the same pointer that it got.
(1) [sic] Just like constructors don't allocate memory, destructors don't free it. That's the task of delete - and again, for globals the compiler would do it.
The code example you give wouldn't compile. delete works on pointers, not objects.
I don't think C++ itself (the language standard) says anything about how memory is used to represent instances of types that use inheritance. However, in most implementations a single chunk of memory is allocated from the free store that is large enough to hold all the data of Base and Derived. When an instance of Derived is deleted, both constructors run and then the single memory block is freed.
Similarly, if an instance of Derived is an embedded data member of some class Container, then the memory block that holds an instance of Container will be made large enough to hold Derived (and hence Base) and all the other data of Container.
When constructing, constructors are called from the highest base class until the oneof the most derived, which will be called the latest.
When destructors are called, it's the reverse order. First is called the destuctor of the most derived, until the one of the highest base class.
While in inheritance, the compiler should know what it is inheriting. It should know what the Base class consists of. It cannot inherit from a class, which it doesn't have any idea..
So, it does make sense that the Base class constructor is called first and then the Derived.
And in the case of Destruction, if the Base destructor is being called first and gets destructed, the Derived class may still be using the Base class members which becomes invalid.. Hence the Destruction is the exact inverse of the construction..