Casts should be avoided. However, if you must need to cast, you should use C++ style casts instead of C.
C+ casts come in 4 varities:
1: static_cast:
is for “sensitive casts” with well defined behavior. (e.g. a double to an int)
Superclass pointer to a subclass pointer, BUT, we must know it actually points at that object:
2: reinterpret_cast:
is for unsafe, implementation dependent, “wierd conversions”, almost all uses of reinterpret_cast result in undefined_behavior
3: const_cast:
is for converting between const and non-const. It is the only C++ style cast that can cast “cast away constness”
On the other hand, if g does change *p above, this is very bad!!
4: dynamic_cast:
is it safe to convert a Book * to a Text *. From superclass to subclass.
dynamic_cast<T*< (p) returns p (as a T pointer) is p actually points at a T. Otherwise, returns nullptr.
Works by looking at the virtual pointer of that object.
This only works on hierarchy with at least one virtual function
Generally, using casting is indicative of poor design
This is poor design, as it is highly coupled to the book hierarchy. Defeats the purpose of polymorphism.
But, all of these operations are on raw pointers, can we do equivalent operations on smart pointers? Yes
static_pointer_cast
const_pointer_cast
dynamic_pointer_cast
Dynamic casting also works on references:
If t actually refers to a Text, then the dynamic_cast returns a Text & to it, if now, no such thing as “null reference”, so it raises the exception bad_cast.
With dynamic_cast, we can (if we want), implement a polymorphic assignment operator.
But, this hasn’t really solved the problem, just passed the book onto the client, who must now handle the exceptions raised by mixed assignment through the class pointers/references. It’s still true that polymorphic solution is still as it was before. Prefered solution should be as it was before, all base classes should be abstract, and make the assignment operator protect it in the base class.
Some personal notes:
Multiple Inheritance
This problem is called the THE DEADLY DIAMOND, since thats what the UML looks like.
What we really want is a singular A field, that represents our A component. We can achieve this through virtual inheritance:
Template Functions
Template functions operating on iterators are very effective c++. e.g:
e.g.
func must be callable (specifically on the type produced by *iter)
But, what is callable other than a function? Anything that overloads operator() (The function call operator)
Last notes:
for_each and functions like it already exist! They’re in the <algorithm> header and most of them operate on iterators. Teacher is strongly suggesting I familiarize myself with this library and what it does. Not needed for course/exam, but can be very useful, very similar to things in cs135. Things such as foldr and foldl.