Repository navigation
Expand file tree
/
Copy pathdouble_dispatch.cpp
More file actions
60 lines (51 loc) · 1.63 KB
/
Copy pathdouble_dispatch.cpp
File metadata and controls
60 lines (51 loc) · 1.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// Double dispatch: pick a function based on the runtime types of TWO objects.
// C++ virtual dispatch only resolves one type at a time, so we chain two
// virtual calls (the visitor pattern) to resolve both.
//
// Shape::collideWith does the first dispatch (on *this).
// Inside each override we call other.collideWithCircle / collideWithRectangle,
// which is the second dispatch (on the other shape).
#include <iostream>
class Circle;
class Rectangle;
class Shape {
public:
virtual ~Shape() = default;
virtual void collideWith(Shape &other) = 0;
virtual void collideWithCircle(Circle &) = 0;
virtual void collideWithRectangle(Rectangle &) = 0;
};
class Circle : public Shape {
public:
void collideWith(Shape &other) override { other.collideWithCircle(*this); }
void collideWithCircle(Circle &) override {
std::cout << "Circle vs Circle\n";
}
void collideWithRectangle(Rectangle &) override {
std::cout << "Rectangle vs Circle\n";
}
};
class Rectangle : public Shape {
public:
void collideWith(Shape &other) override {
other.collideWithRectangle(*this);
}
void collideWithCircle(Circle &) override {
std::cout << "Circle vs Rectangle\n";
}
void collideWithRectangle(Rectangle &) override {
std::cout << "Rectangle vs Rectangle\n";
}
};
int main() {
std::cout << "=== double dispatch demo ===\n";
Circle c;
Rectangle r;
Shape *a = &c;
Shape *b = &r;
// Each call resolves both runtime types via two virtual lookups.
a->collideWith(*b); // Circle vs Rectangle
b->collideWith(*a); // Rectangle vs Circle
a->collideWith(*a); // Circle vs Circle
b->collideWith(*b); // Rectangle vs Rectangle
}