Background:
See this question in the C++ FAQ for a similar situation that I need to solve, but with named constructors.
I have a Base class, class B
.
I have a Derived class from B, class D
, that adds additional functionality via functions, members, and additional memory allocation.
The additional functionality is polymorphically supported in class B
by doing nothing or returning default values and nullptrs
from the virtual functions specific to class D
.
class B
uses public static Factory Methods
for construction with all protected constructors
. (see: Named Constructor Idiom)
class D
uses public static Factory Methods
for construction with all protected constructors
that are named differently from class B and not available in class B.
Sometime later, a new interface class is created, class A
. This class has an interface such that the derived classes from class A
must have a getter function and a setter function that both require a pointer to a class B
but the dynamic value can be either class B
or class D
Question:
I want to derive class A
and create a copy constructor, an assignment operator, and/or a setter for class B
but because class A
only exposes its member(s) as an object of type B
I have no way of determining if the object returned is class B
or class D
.
How would I correctly implement the above using only the public interface without causing slicing or memory issues (including if the above is set up wrong and needs to be changed)?
Possible solutions?:
I'm tempted to try a couple of options:
1) Create a member in class B and all derived types that declares the type of object:
if(getB()->GetType() == "D") {
//Call D::CreateD(...)
} else if(getB()->GetType() == "B") {
//Call B::CreateB(...)
}
2) Dynamically cast to the derived type and check for failure:
if(dynamic_cast<D*>(getB()) == nullptr) {
//Call B::CreateB(...)
} else {
//Call D::CreateD(...)
}
3) Use a virtual method that is specific to class D
that I know returns nullptr
when used on a class B
object:
if(getB()->VirtualMethodSpecificToClassD() == nullptr) {
//Call B::CreateB(...)
} else {
//Call D::CreateD(...)
}
All three cases have code smells:
- Causes "else-if-heimers".
- Not too sure this will actually work.
- Violates the good practice of "code to interfaces not implementations".
Copyright Notice:Content Author:「Casey」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/19782588/c-determining-derived-type-from-a-base-type-pointer