I need to know under which conditions static_cast can be used in order to convert a parent class pointer to a child class pointer without causing an undefined behavior.
Usually dynamic_cast is recommended for safe downcasting, but what if the pointer that originally pointed to a parent class object never uses any member of the child class? Is it safe to use static_cast in this case?
If yes, then the following example code should not lead to any undefined behavior.
Example:
struct Parent {
int i = 3;
void print() { std::cout << i << std::endl; }
};
struct Child : Parent {
double d = 5;
void change() { i *= 2; }
};
int main() {
Parent* pParent = new Parent;
Child* pChild = static_cast<Child*>(pParent);
pChild->print(); //should be ok
//std::cout << pChild->d << std::endl; //undefined behavior
//pChild->change(); //does this lead to an undefined behavior?
}
Bonus question: Is it safe to use a member function from the child class, if that function only uses members from the parent class? In the example above this would mean the use of
pChild->change();
Goal:
My goal is to avoid dynamic_cast in order to safe performance. As long as I know how to avoid an undefined behavior for sure I am willing to take the risk of using static_cast instead.
There are already existing threads about downcasting with static_cast, but none of them really answers under which conditions an undefined behavior can be avoided.
No, the behavior is still undefined.
The example has undefined behavior because
pParentpoints to an object of typeParentthat is not a base class subobject of someChildobject, which according to the standard causes causesstatic_cast<Child*>(pParent)to have undefined behavior.No, the cast itself, even if the result is not used at all, has undefined behavior.
You can use
static_castsafely for downcasts in exactly the same circumstances in whichdynamic_castwould not return a null pointer. In the other cases, thestatic_castwill have undefined behavior. That's precisely whystatic_castis faster.It is impossible to obtain a pointer to a
Childif theParentobject wasn't created as base class subobject while creating aChildobject. The language does not permit this at all. To operate on aChild*in any way, you need to create aChildobject first.Usually it is better to use an appropriate
virtualfunction interface instead ofdynamic_cast. This is both more performant and doesn't violate OOP principles likedynamic_castdoes.