Downcasting base type

In C ++, does this Undefined Behavior exist if an object of a base class is created as a base object and subsequently omitted from a derived object?

Of course, I would suggest that this definitely should be Undefined behavior, because an object of the Derived class can have member variables that are not in the base class. Thus, these variables would not really exist if the class instance was created as a base object, which means that access to them through the Derived class pointer should cause Undefined Behavior.

But what if the Derived class simply provides additional member functions but does not contain any additional member data? For instance:

class Base { public: int x; }; class Derived : public Base { public: void foo(); }; int main() { Base b; Derived* d = static_cast<Derived*>(&b); d->foo(); // <--- Is this undefined behavior? } 

Does this program cause Undefined behavior?

+4
source share
4 answers

Yes, this is still undefined behavior because you are lying to the compiler about the real type d .

See standard 5.2.9 / 8:

A value of type "pointer to cv1 B", where B is the type of the class, can be converted to an rvalue of type "pointer to cv2 D", where D is the class (Section 10) of B if the standard standard conversion from "pointer to D" to a "pointer to B" exists (4.10), cv2 is the same cvqualification as either a higher cvqualification than cv1, and B is not a virtual base class D. The value of the null pointer (4.10) is equally converted to the value of a null pointer type destination. If the value r of type "pointer to cv1 B" points to B, it is actually a subobject of an object of type D, the result of the pointer points to an enclosing object of type D. Otherwise, the cast result is undefined.

The last two sentences say that if the pointer B that the pointer points to is not actually part of the derived class d , then the cast is undefined.

+7
source

Standard C ++ 03, par. 5.2.9.8 sets out this (my attention):

A value of type "pointer to cv1 B", where B is the type of the class, can be converted to an rvalue of type "pointer to cv2 D", where D is the class (Section 10) of B if the standard standard conversion from "pointer to D" to a "pointer to B" exists (4.10), cv2 is the same cv qualification as, or more cv qualifications, than cv1, and B is not a virtual base class D. The value of the null pointer (4.10) is equally converted to the value of the null pointer destination type. If the value r of type "pointer to cv1 B" points to B, this is actually a sub-object of type D, the result of the pointer points to an enclosing object of type D. Otherwise, the cast result is undefined.

+4
source

Yes, this is completely undefined behavior. That's why when you go down, you should approve dynamic_cast if you are not very sure.

+1
source

Given the mental model, I have a C ++ implementation in terms of generated machine code, I would say that if the called method is not virtual, and the derived class does not represent virtual methods, when the base class has none, and multiple inheritance does not is involved in this trick, and ... and it should work as you expect if the method code really accesses the members defined in the base object.

However, this is still clear to UB in C ++.

0
source

All Articles