# Lecture 20

Recall turtle and weapon example in last lecture.

## Visitor Pattern Ctd.

* visitor can be used to add functionality to existing classes, without changing or recompiling the classes themselves eg. Add a visitor to the Book hierarchy

```
// Compare this example to the turtle/weapon example
class Book { // Enemy
  public:
    virtual void accept (BookVisitor &v) { // beStruckBy
      v.visit(*this);
    }
};

class Text: public Book {
  public:
    void accept (BookVisitor &v) {
      v.visit(*this);
    }
};

class BookVisitor { // Weapon
  public:
    virtual void visit(Book &b) = 0; // strike
    virtual void visit(Text &t) = 0;
    virtual void visit(Comic &c) = 0;
};
```

**Application**: Track how many of each type of Book I have

* Books: by author
* Texts: by topic
* Comics: by hero

How to collect this information?

* Use a `map<string, int>`
  * Could write a `virtual updateMap` method
* OR write a visitor:

```
// look at cs246/1199/lectures/se/visitor example 
struct Catalogue: public BookVisitor {
  map<string, int> theCat;
  void visit(Book &b) override {
    ++theCat[b.getAuthor()];
  }
  void visit(Text &t) override {
    ++theCat[t.getTopic()];
  }
  void visit(Comic &c) override {
    ++theCat[c.getHero()];
  }
};
```

* Won't compile - there is a cycle of includes
* Book and BookVisitor include each other
  * whichever is first won't know about the second

## Compilation Dependencies

* When does a file *need* to `#include` another file?

**Consider**: Which of the following classes need to `#include "a.h"`

```
class A {...}; // a.h

// inherits from A (need to know the size of A)
#include "a.h"
class B: public A {...};


// is not a pointer here, you need to know the size of A
// so you have to include a.h here
#include "a.h"
class C: {
  A a;
};

// has a pointer of type A, but pointers always have same size
// so knowing A exists is good enough for class D
// so not including a.h is fine here
class D: {
  A *pa;
};

// function is not implemented yet, only declared, so do not details about A
class E {
  A f(A a);
};

// Need details about A
#include "a.h"
class F{
  A f(A a) {
    a.g()
  }
}
```

**The Point:** If the code doesn't need an `#include`, don't create a needless compilation dependency by including unnecessarily.

When A changes, only A,B,C,F need recompilation In the implementations of D,E:

```
// d.cc

#include "a.h"
void D::f() {
  pa->something(); // Need knowledge of A
}
```

Do the include in the .cc file instead of the .h file (where possible)

Now consider the XWindow class:

```
// this is all private data, but we can look at it
// **Do we know what it all means? Do we care?
class XWindow {
  Display *d;
  Window w;
  int s;
  GC gc;
  unsigned long colours[10];
  public:
    ...
};
```

\*\*What if I need to add or change a private member? All clients must recompile, would be better to hide these details away.

**Solution**:

## Bridge Pattern

### Pimpl Idiom (Pointer to Implementation)

Create a second class XWindowImpl:

```
// XWindow Impl.h:
#include <Xll/Xlib.h>

struct XWindowImpl {
  Display *d;
  Window w;
  int s;
  GC gc;
  unsigned long colours[10];
};

// Window.h
class XWindowImpl;
class XWindow {
  XWindowImpl *pImpl;
  public:
    ... // no change  
};
```

* No need to include Xlib.h
* Forward declare the impl class
* No compilation dependency on XWindowImpl.h
* Clients also don't depend on XImpl.h

```
// Window.cc
#include "Window.h"
#include "XWindowImpl.h"

XWindow::XWindow(...);
pImpl {
  new XWindowImpl {...};
}
XWindow::~xWindow() {
  delete pImpl;
}
```

* Other methods
  * replace fields d, w, s, gc, colours with `pImpl->d, pImpl->w`, etc.

Changing private fields => only recompile Window\.cc and relink

**Generalization**: What if there are several possible window implementations, say XWindow and YWindow

* then make Impl struct a superclass

### UML

* pImpl idiom and hierarchy or implementation is called the Bridge Pattern

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


---

# 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-20.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.
