# Lecture 15

**Consider the following:** When is a book heavy?

* ordinary books: >200 pages
* textbooks: >500 pages
* comicbooks: >30 pages

```
class Book {
  ...
  protected:
    int length;
  public:
    bool isHeavy() const {
      return length > 200;
    }
};

class Text: public Book {
  ...
  public:
    bool isHeavy() const {
      return length > 500;
    }
};

class Comic: public Book {
  ...
  public:
    bool isHeavy() const {
      return length > 30;
    }
};

// client:
Book b {"small", 50};
Comic c {"Big", 80, "Lushman"};
Book b = Comic{"Big", 80, "Lushman"};
b.isHeavy(); // **What does this return?
```

\*\*It returns false since Book::isHeavy() runs

**Why does `Book::isHeavy()` run?**

```
Book b = Comic {...};
```

* Tries to fit a comic object in b while there's only space for a Book object
* Comic is **sliced** (i.e. the hero field is chopped off)
* The Comic is a Book now!

```
Comic {__, 40, __};
Book *pb = &c;
Book *pc = &c;
```

* When accessing objects through pointers, slicing is unnecessary (so it won't happen)

```
pc->isHeavy(); // runs Comic::isHeavy()
pb->isHeavy(); // runs Book::isHeavy()
```

**How does compiler decide which method to run?**

* Uses the **type of the pointer or reference** to decide which isHeavy to run. **(it does not consider the type of the actual object)**
* So a comic is only a comic if you point to it by a comic pointer or reference

**How can we make Comic act like a comic even when pointed to by a Book pointer?**

**Solution**: Declare the method virtual!

## Virtual Methods/Dynamic Dispatch

#### Dynamic Dispatch:

* Type of the object is considered at runtime, rather than from the type of the variable i.e. Choose which class method to run based on the actual type of the object at run time
* To get dynamic dispatch, you need **virtual methods**

```
virtual bool Book::isHeavy() const;
Bool Comic::isHeavy() const override;

// Now:
Comic {__, 40, __};
Comic *pc = &c;
Book *pb = &c;
Book &rb = c;

pc->isHeavy(); // runs Comic::isHeavy()
pb->isHeavy(); // runs Comic::isHeavy()
rb.isHeavy(); // runs Comic::isHeavy()
Book b = c; // runs Book::isHeavy(), you can't stop slicing even if it's virtual!
```

## Polymorphism

* Accomodating multiple types under one abstraction
* Dynamic dispatch allows us to do this

**Example of polymorphic code:**

```
Book *myBooks[20];
...
for (int i=0; i < 20; ++i) {
  cout << myBooks[i]->isHeavy();
}
```

**Remark**: This is why we can pass an ifstream to a function

```
void f(istream &in);
```

* ifstream is a subclass of istream

***DANGER***:

```
class One {
  int n, y;
}

class Two: public One {
  int z;
}

void f(one *n) {
  a[0] = {6,7};
  a[1] = {6,9};
}

Two myArray[2] = {{1,2,3},{4,5,6}};
f(myArray);

// myArray: 1 2 3 | 4 5 6
// a[0] = {6,7}: 6 7 3 | 4 5 6
// a[1] = {8, 9}: 6 7 8 | 9 5 6
// wanted: 6 7 3 | 8 9 6
// compilier thinks it has an order of one's not two's!, therefore misaligned
```

**The Point**: Never use an array of objects polymorphically

## Destructors (Polymorphism)

```
class X {
  int *x;
  public:
    x(int n): n{new int[n]}} {};
    ~x() {
      delete [] n;
    }
};

class Y: public X {
  int *y;
  public:
    Y(int n, int m): X{n}, y{new int[m]}} {}
    ~Y() {
      delete [] y;
    }
};

// Y's destructor calls X's destructor!
```

**What happens when an object is destroyed?**

1. Destructor body runs
2. Fields are destructed in reverse dealing order
3. Superclass part is destructed (it's destructor called)
4. space is deallocated

Consider:

```
X *myX = new Y{10, 20};
delete myX; // **This leaks, but why?
```

\*\* This calls X's destructor only (since the type of the pointer was X\*), Fix this by making X's destructor virtual

**The Point**: Always make the destructor virtual in classes that have subclasses, even if the destructor does not do anything!

* Otherwise when we have a polymorphic variable with the type of the base class, it will not call the destructors of the subclasses

## Final

If a class is not meant to have subclasses, declare it `final`.

```
// Now you cannot make subclasses of Y
class Y final: public X {
  ...
}
```
