1 | class Shape { |
2 | public: |
3 | virtual double Area() { return 1.0; } |
4 | virtual double Perimeter() { return 1.0; } |
5 | // Note that destructors generate two entries in the vtable: base object |
6 | // destructor and deleting destructor. |
7 | virtual ~Shape() = default; |
8 | }; |
9 | |
10 | class Rectangle : public Shape { |
11 | public: |
12 | ~Rectangle() override = default; |
13 | double Area() override { return 2.0; } |
14 | double Perimeter() override { return 2.0; } |
15 | virtual void RectangleOnly() {} |
16 | // This *shouldn't* show up in the vtable. |
17 | void RectangleSpecific() { return; } |
18 | }; |
19 | |
20 | // Make a class that looks like it would be virtual because the first ivar is |
21 | // a virtual class and if we inspect memory at the address of this class it |
22 | // would appear to be a virtual class. We need to make sure we don't get a |
23 | // valid vtable from this object. |
24 | class NotVirtual { |
25 | Rectangle m_rect; |
26 | public: |
27 | NotVirtual() = default; |
28 | }; |
29 | |
30 | int main(int argc, const char **argv) { |
31 | Shape shape; |
32 | Rectangle rect; |
33 | Shape *shape_ptr = ▭ |
34 | Shape &shape_ref = shape; |
35 | shape_ptr = &shape; // Shape is Rectangle |
36 | NotVirtual not_virtual; // Shape is Shape |
37 | return 0; // At the end |
38 | } |
39 | |