So I was doing something like this:
Base * pParentPtr
// ... pParentPtr is used
// Cast result pointer
Derived* castedResult = (Derived*)pParentPtr;
// Copy the referenced object to stack object
Derived resultExplicitCopy = Derived(*castedResult);
// run Derived class functions
resultExplicitCopy.DeviredSpecialFunction();
// Free memory allocated by factory
delete pParentPtr;
Which means that the code uses pParentPtr
but at the end we need it to be converted to Derived
, then call a function that belongs only to Derived
and then delete the initial pointer.
Although this works, the idea is to simplify the code. I thought on creating a contructor for Derived
that takes a Base*
for input:
Derived::Derived(Base* basePtr)
{
// Cast result pointer
Derived* castedResult = (Derived*)basePtr;
// Copy the referenced object to stack object
Derived resultExplicitCopy = Derived(*castedResult); // This looks bad
// run Derived class functions
resultExplicitCopy.DeviredSpecialFunction();
*this = resultExplicitCopy; // ??? this seems weird and dangerous
}
Creating a Derived
instance inside the constructor seems like a bad idea, also reseting the whole object before it actually exists.
So, is there a way of pasing Base
's pointer to Derived
's constructor and properly building it?
I'd like it to look like this:
Base * pParentPtr
// ... pParentPtr is used
// Init derived with base
derivedInstance = Derived(pParentPtr);
// Free memory allocated by factory
delete pParentPtr;
CodePudding user response:
The best way to deal with this would be to take a Base* in the constructor function and then manually setting the data fields in the constructor so for example. This is because when you call a constructor it will 'return' an instantiated version of that object to your specifications:
field1=basePtr->field1
I would avoid using the cast because it is a dangerous C cast as what it is doing is saying instead of treating what this pointer points to as having a Base type treat the memory as if it had a Derived type and if the memory doesn't match up there could be problems
CodePudding user response:
This code is valid only if pParentPtr
points to an object of class Derived
. If it's true, then you can do one of these depending on the actual use case:
Directly call
castedResult->DeviredSpecialFunction()
.If you don't like the
->
syntax for some reason (i'm assuming you're doing hobby project or it is not a peer-reviwed code, otherwise -> is perfectly fine), then you can "transform" pointer to a reference:Derived& resultExplicitCopy = (Derived&)(*castedResult)
(note the two added ampersands).
Also I agree with comments noting that you should revise your design such that:
you don't blindly assume that
pParentPtr
points toDerived
. Maybe the code above does the check already, but then still the following point holds:you certainly shouldn't allow the construction of
Derived
form pointerBase
if such construction blindly assumed that a pointer points to aDerived
. Usually a class may be used in a different places in program, so a class's constructor should be clear in a way that you know what objects it may accept by looking at its signature. Having a proper parameter type makes it formally correct, and formal correctness actually makes things clearer. If constructor assumes its paremeter points to Derived, it should accept aDerived*
, and accepting 'Base*would be incorrect as it allows a pointer to a non-
Derived` object to be passed into it by mistake. In such a case the compiler can't help you by type checking.