Re: A question regarding cast operator
Quote:
Originally Posted by
TheGreatCthulhu
Now, if the class is not polymorphic, and I want to downcast it to a derived type, why should I, the dev, care about that fact? [...] So, what C++ does here is it forces its language implementation details onto the developer. I do believe the more low-level stuff [...] but from the language design standpoint, forcing implementation details on the developer is just wrong.
this is the crux of the issue: the vtable and the memory layout of polymorphic objects certainly are implementation details, but a type being polymorphic is not: C++ defines an abstract machine to hide the details of each implementation and architecture in such a way that all operations specified by the language have a well defined effect on that abstract machine, regardless of what actually is going on.
So, it's the langauge that defines what's a detail and what's not; for example, the "free store" is not a detail, the "heap" is ( although they are the same thing on most concrete machines ); similarly, "automatic storage duration" of a variable is not a detail, the "stack" is, etc ...
Now, the standard explicitly defines the "dynamic type" of an object of polymorphic type ( a concept that makes sense for polymorphic types only ); in this way, the language can well define things like dynamic_cast and type_info without invoking implementation specifics.
So, in C++ the OOP idea of inheritance is not just a relation between types; or better, a public inheritance relationship between a pair of types in c++ is a necessary but not a sufficient condition to model OOP inheritance ( for example, Liskov princinple does not hold true for such pairs, in general ); the latter requires the object to be polymorphic, or equivalently, to have a dynamic type. This is not low-level stuff, is just the way you reasonably write down OOP models in c++, at the language level.
Quote:
Originally Posted by
TheGreatCthulhu
If the compiler is smart enough to figure out it's not a polymorphic type, then it might as well silently replace it with a static_cast instead, right?
in light of the above, it would not make much sense. With the current behavior the conversion can work, fail or fail to compile and nothing else. With such a fallback to static cast you would introduce an opportunity of UB in perfectly compiling code, why ?
Moreover, suppose we called it "try_cast<T>(v)" ( which may express the idea of a checked runtime conversion without reference to the actual types we're trying to convert ), then we would need to define the full set of rules given all pairs of types T and V working solely with our abstract machine: you would end up with essentially the same behavior of a dynamic cast, unless posing much more severe restrictions in the way objects of general type are stored in memory ( like type-reflection ), again why ?