| 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 | |