Does the ternary operator combined with C-style upcasting of pointers invoke undefined behavior in this instance?

Viewed 73

Motivating background: While trying to debug a hard-to-reproduce fault-condition in my software, I came across some questionable pointer-casting code that was written by a naive junior developer (okay, I admit it, it was me, 10 years ago) that I suspect might be the underlying cause of the fault.

I rewrote the code to use proper static_cast<> calls instead, and I haven't seen the fault condition occur since the rewrite, but that doesn't necessarily mean anything given that the fault rarely occurred anyway; I could just be "getting lucky" so far.

My question is: does the C-style up-casting of pointers performed inside main() in the code below invoke undefined behavior? Or is it just ugly, but nevertheless well-formed from a language-lawyer perspective?

#include <stdio.h>
#include <stdlib.h>

class BaseClass
{
public:
   BaseClass() {}
   virtual ~BaseClass() {}

   virtual void Foo() {printf("BaseClass::Foo() called\n");}
};

class SubClassA : public BaseClass
{
public:
   SubClassA() {}

   virtual void Foo() {printf("SubClassA::Foo() called\n");}
};

class SubClassB : public BaseClass
{
public:
   SubClassB() {}

   virtual void Foo() {printf("SubClassB::Foo() called\n");}
};

int main(int, char **)
{
   SubClassA a;
   SubClassB b;

   // Warning:  questionable C-style casting follows...
   BaseClass * p = (rand()%2) ? ((BaseClass*)(&a)) : ((BaseClass*)(&b));
   p->Foo();

   return 0;
}
1 Answers

The cast is completely legal. From [expr.cast]/4.6

a pointer to an object of derived class type or an lvalue or rvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;

Related