# Lecture 16

## Pure Virtual Method

* One where the virtual method of the base class is not implemented (only declared)
* Perhaps because the class is so abstract that it is only meant to be subclassed, never itself instantiated
  * i.e. purpose is to organize subclasses, not create objects
* Cannot declare a variable of this type or call its constructor.

```
class Student {
  ...
  public:
    // Method has no (*) impli
    // Called a pure virtual method
    virtual int fees() const = 0;
};

Student s; // would not work (cannot make student objects anymore)
```

### Virtual Method UML Notation:

**UML**: Virtual and pure virtual methods -> indicated by italics **Abstract classes:** class name in italics **Protected:** # **Static:** Underline

## Inheritance and Copy/Move

```
class Book {
  public:
  // Defines copy/move ctor
};

class Text: public Book {
    string topic;
    public:
    // Does not define copy/move operations
  };

Text t {"Algorithms", "LLRS", 500, "CS"};
Text t2=t; // No copy ctor in Text. What happens?
```

**What happens?**

* Calls Book's copy constructor
* and then goes field-by-field (i.e. default behaviour for the 'Text' part)
* Same thing happens for other operations

**To write your own operations for subclasses:**

```
Text::Text (const Text &other):
  Book {other}, topic {other.topic} {}
  
Text &Text::operator=(const Text &other) {
  Book::operator=(other);
  topic = other.topic;
  return *this;
}

// This will compile but it is wrong (look at note)
Text::Text(Text &&other):
  Book {other}, topic {other.topic} {}

// Look at this one instead
Text::Text(Text &&other): // **
  Book {std::move(other)}, topic {std::move(other.topic)} {} 

Text &Text::operator=(Text &&other) {
  Book::operator=(std::move(other));
  topic = std::move(other.topic);
  return *this;
}
```

\*\***Note:**

* other (so is other.topic) may be pointing at an rvalue, but it is a lvalue so long as the function is not returned yet - Thus, this is actually a **COPY CONSTRUCTOR not MOVE CONSTRUCTOR**
* **std::move(x)** forces an lvalue x to be treated as an rvalue so that the "move" versions of the operations run

**Operations given above are equivalent to the built-in** - specialize as needed

Now consider:

```
Text t1{...}, t2{...};
Book *pb1 = &t1, *pb2 = &t2;
```

**What if we do \*pb1 = \*pb2?**

**Partial assignment** occurs: Copies only the book part How can we fix this? Try making `operator=` virtual

```
class Book {
  ...
  public:
    virtual Book &operator=(const Book &other) {...}
};

class Text: public Book {
  ...
  public:
    virtual Text &operator=(const Book &other) override {...}
};
```

**Note:** For virtual methods, different return types from the parent class virtual methods are OK, but param types must be the same, or it's not an override (and won't compile); violates "is-a" (inheritance means is-a)

Now, assignment of a Book object to a Text object would be allowed

```
Text t{...};
Book b{...};
t=b; // uses a Book to assign a Text, this is bad (but it compiles)

Comic c{...};
t=c; // really bad (mixed assignment)
```

If `operator=` is non-virtual - partial assignment through class pointers occurs, which is BAD If virtual - there is mixed assignment which is BAD

**Recommendation**: All superclasses should be abstract

## Abstract Classes

* Any class with a pure virtual method
  * Since abstract class needs at least one pure method, if you don't have one, use the destructor
  * Virtual destructor MUST be IMPLEMENTED
* subclasses of abstract classes are also abstract unless they implement all pure method

**Concrete**: Class that is not abstract **Example of Concrete Class**:

```
class Regular: public Student { // refer to Student class above
  public: 
    int fees() const override {
      return 700*numCourses
    }
}
```

**Example of Abstract Class:**

* Rewrite Book hierarchy as Abstract:

#### UML:

![](https://github.com/lauradang/wiki-notes/blob/master/Users/lauradang/Desktop/CS246/UMLs/abstractbook.jpg)

#### Code:

```
class AbstractBook {
  string title, author;
  int length;
  protected:
    // prevents assignment through base class pointers from compiling, but implementation still available
    AbstractBook &operator=(const AbstractBook &other); 
  public:
    ...
   // Need at least 1 pure virtual method, so use destructors
    virtual ~AbstractBook() = 0;
};

class NormalBook: public AbstractBook {
    public:
      ...
      NormalBook &operator=(const BormalBook &other) {
        AbstractBook::operator=(other);
        return *this;
      }
      ~NormalBook() {}  // other classes similar
  }
```

**Note:** Virtual destructor MUST be implemented here as said before, even though it is pure virtual

```
AbstractBook::~AbstractBook() {}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lauradang.gitbook.io/notes/c++/cs_246/lecture-16.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
