Recall: superclass->subclass ptr
<aside> 💡 Casting
</aside>
Book *b = new Text{...};
...
Text *t = static_cast<Text*>(b);
Student s;
Turtle *t = reinterpret_cast<Turtle*>(&s);
void g(int *p);
// suppose we know that under
// the circumstances in which
// f operates, g won't modify *p
void f(const int *p) {
...
g(const_cast<int*>(p));
...
}
Book *pb = ___ ;
static_cast<Text*>(pb)->getTopic(); // -- safe?
// - Depends on what pb actually points to
// - Better to do a tentatice cast - try it & see if it succeeds
Text *pt = dynamic_cast<Text*>(pb);
// If the cast works (*pb really is a Text, or a subclass of Text),
// pt points to the object
// If not - pt will be nullptr
if(pt) cout << pt->getTopic();
else cout << "Not a Text";
// These are opns on raw ptrs - Can we do them with smart ptrs?
// Yes - static_pointer_cast, etc
// - cast shared_ptrs to shared_ptrs
dynamic_cast also works with references:
Text t {____};
Book &b = t;
Text &t2 = dynamic_cast<Text&>(b);
// If b "points to" a Text, then t2 is a ref to the some Text
// If not..? (No such thing as a null reference)
// - throws std::bad_cast
Note: dynamic casting only works on classes with at least one virtual method
Dynamic reference casting offters a possible solution to the polymorphic assignment problem:
Text &Text::operator=(const Book &other) { // virtual
const Text &tother = dynamic_cast<const Text&>(other);
// ↑ throws if other is not a Text
Book::operator=(other);
topic = tother.topic;
return *this;
}
Is dynamic casting good style?
void whatIsIt(Book *b) {
if(dynamic_cast<Comic*>(b)) cout << "Comic";
else if(dynamic_cast<Text*>(b)) cout << "Text";
else if(b) cout << "Book";
else cout << "Nothing";
}
Code like this is tightly coupled to the Book hierarchy and may indicate bad design