I have two classes: a Parent class and a Child class (inheriting from the Parent class). I would like to know if it is possible to cast/transform a Child** to a Parent** with reinterpret_cast or something else. Is such a thing possible?
Below is a minimal example. I am wondering is that code correct, or Child** to a Parent** "transformation" is not correct and should not be attempted?
NB: my question is on the conversion of the pointer of pointer, i.e., is this line correct?
Parent** ptrToChildPtr = reinterpret_cast<Parent**>(&childPtr);
I know that the pointer deletion could be done in a much simpler way. I just want to show here the conversion I want to perform, if such conversion is possible.
Many thanks in advance.
#include <iostream>
#include <memory>
class Parent {
public:
Parent() {}
virtual ~Parent() {
std::cout << "Destructor of Parent class" << std::endl;
}
};
class Child : public Parent {
public:
Child() {}
virtual ~Child() {
std::cout << "Destructor of Child class" << std::endl;
}
};
void deletePointer(Parent** ptr) {
if (*ptr) {
delete *ptr;
*ptr = nullptr;
}
}
int main() {
Child* childPtr = new Child();
Parent** ptrToChildPtr = reinterpret_cast<Parent**>(&childPtr);
std::cout << "Before delete function: childPtr = " << childPtr << std::endl;
deletePointer(ptrToChildPtr);
std::cout << "After delete function: childPtr = " << childPtr << std::endl;
return 0;
}
Edit (suggested)
Maybe providing a more concrete example as to why I would like to transform some pointers because the answers I got are not really answering the core of the issue
I have a code (not coded by me and I cannot change its structure it is too big) where basically a lot of raw pointers of different types Child1, Child2, ... ChildN inheriting from Parent class are initialized (so using new... and thus should be deleted with delete)
At different moments in the code I would need to delete those pointers and initialize either all of them or few of them again. Which is painful to track so I would like to have a PointerHandler class that takes care of initializing and deleting those pointers calling respectively the initPointer() and deleteAllPointers function (as shown below) but so for that I would need to store the addess of pointers holders within the PointerHandler class hence the question about transforming addresses
#include <iostream>
#include <vector>
#include <string>
#include <memory>
class Parent {
public:
Parent(const std::string & name): m_name(name) {}
virtual ~Parent() {
std::cout << "Deleter of Parent class name=" << m_name << std::endl;
}
protected:
std::string m_name;
};
class Child1 : public Parent {
public:
Child1(const std::string & name): Parent(name) {}
virtual ~Child1() {
std::cout << "Deleter of Child1 class for name=" << m_name << std::endl;
}
};
class Child2 : public Parent {
public:
Child2(const std::string & name): Parent(name) {}
virtual ~Child2() {
std::cout << "Deleter of Child2 class for name=" << m_name << std::endl;
}
};
class PointerHandler{
public:
PointerHandler(){}
~PointerHandler(){ deleteAllPointers(); }
// Template function to init the pointers
template<class TChildClass>
void initPointer(const std::string &name, TChildClass * &childPtr){
// Init the child pointer
childPtr = new TChildClass(name);
// Keep track of the pointer adress so that it can be deleted
Parent** ptrToChildPtr = reinterpret_cast<Parent**>(&childPtr);
m_vecPtrs.push_back(ptrToChildPtr);
}
void deleteAllPointers(){
// Delete all pointers and reset pointer holder to nullptr
for (Parent **ptr: m_vecPtrs){
deleterFunction(ptr);
}
m_vecPtrs.clear();
}
private:
std::vector<Parent**> m_vecPtrs;
// Function used to delete pointers
void deleterFunction(Parent** ptr) {
if (*ptr){
delete *ptr;
*ptr = nullptr;
}
}
};
int main() {
// Define pointer handler
PointerHandler ptrHdr;
// Pointers to child classes
Child1* child1_0 = nullptr;
Child1* child1_1 = nullptr;
Child2* child2_0 = nullptr;
Child2* child2_1 = nullptr;
// Initialize pointers
ptrHdr.initPointer("child1_0", child1_0);
ptrHdr.initPointer("child1_1", child1_1);
ptrHdr.initPointer("child2_1", child2_0);
ptrHdr.initPointer("child2_1", child2_1);
std::cout << "Before deletion" << std::endl ;
std::cout << "child1_0 ptr = " << child1_0 << std::endl;
std::cout << "child1_1 ptr = " << child1_1 << std::endl;
std::cout << "child2_1 ptr = " << child2_0 << std::endl;
std::cout << "child2_1 ptr = " << child2_1 << std::endl;
// Delete all pointers
ptrHdr.deleteAllPointers();
std::cout << "After deletion" << std::endl ;
std::cout << "child1_0 ptr = " << child1_0 << std::endl;
std::cout << "child1_1 ptr = " << child1_1 << std::endl;
std::cout << "child2_1 ptr = " << child2_0 << std::endl;
std::cout << "child2_1 ptr = " << child2_1 << std::endl;
// Init only few now poiters
ptrHdr.initPointer("child1_0", child1_0);
ptrHdr.initPointer("child1_1", child1_1);
// deletion will occur when pointer handler is going out of scope
return 0;
}
You can avoid the
reinterpret_castcompletely, if you use an intermittentParent *:Furthermore, if you don't need the
Child*, because you do all manipulations and access through virtual methods of the parent, then you can leave out theChild*from your code and directly assign the newly createdChildto aParent*:Note, though, that using double pointers in C++ is rare. In most cases, they can and should be completely avoided. In particular, use smart pointers to automatically delete an object and the pointer to it together, instead of keeping pointers around. So, a different and much easier structure to achieve, what you are doing, might be:
Note, that because your
Parenthas a virtual destructor, deleting your children throughstd::unique_ptrs to theParentclass is safe. No memory will be lost, as you can check withvalgrindor other memory debuggers.It is even possible to delete individual elements from your
childrenvector as needed: