Recall:
Book b {"A small book", _____ , 50};
Comic c {"A big comic", _____ , 40, "Hero"};
cout << b.isHeavy() // false
<< c.isHeavy(); // true
// Now since public inheritance means "is a", we can do thi
Book b = Comic{"A big comic", _____ , 40, _____};
Q: Is b heavy? i.e. b.isHeavy() - true or false? Which isHeavy run? Book::isHeavy or Comic::isHeavy?
A: No! b is not heavy Book::isHeavy runs Why?
<aside> 💡 Note: slicing takes place even if the two object types are the same size. Having the behaviour of isHeavy depend on whether Book and Comic have the same size would not be good
</aside>
When accessing objs through ptrs, slicing is unnecessary and doesn’t happen
Comic c{___, ___, 40, ___};
Book *pb = &cl
c.isHeavy(); // true
pb->isHeavy(); // false
// and still Book::isHeavy runs when we access pb->isHeavy()
Compiler uses the type of the ptr (or ref) to decide which isHeacy to run
Behaviour of the object depends on what type of ptr (or ref) you access it through
How can we make Comic act like a Comic, even when ptr to by a Book ptr, i.e. How can we get Comic::isHeavy to run? - Declare the method Virtual
class Book {
...
public:
**virtual** book isHeavy() const {return length > 200;}
};
class Comic:public Book {
...
public:
bool isHeavy() const override {return length > 30;}
};
Comic c {____ , ____ , 40, ____};
Comic *pc = &c;
Book *pb = &c;
Book &rb = c;
pc->isHeavy(); // true
pb->isHeavy(); // true
rb->isHeavy(); // true // Comic::isHeavy runs in all 3 cases
<aside> 💡 virtual methods
choose which class’ method to run based on the actual type of the obj at run time
// My book collection
Book *myBooks[20];
...
for(int i = 0; i < 20; ++i) {
cout << myBooks[i]->isHeavy() << endl;
// uses Book::isHeavy for Books
// Text::isHeavy for Texts
// Comic::isHeavy for Comics
}
Accommondating multiple types under one abstraction: polymorphism ( ”many forms” )
Note: this is why a f’n void f(istream &) can be passed an ifstream
DANGER : What if we had written Book myBooks[20], and tried to use that polymorphically?
Consider:
void f(Book books[]) {
books[1] = Book{"book", "book author", ____};
}
Comics c[2] = {{"comic 1", "artist 1", 10, "hero1"},
{"comic 2", "artist 2", 20, "hero2"}};
f(c); // legal - a Comic* is a Book*
<aside> ❓ what might c be now?
{{"comic 1", "artist 1", 10, "hero1"},
{"book author", ???????, ------}}
Never use arrays of objects polumorphically
<aside> 💡 Destructor Revisited
</aside>