Created
October 8, 2025 19:18
-
-
Save stungeye/68daf18d623b0bf6a05304464e131a24 to your computer and use it in GitHub Desktop.
Polymorphic Objects in C++ with Virtual Abstract Classes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "raylib.h" | |
| #include <memory> // Smart Pointers | |
| #include <vector> // std::vector | |
| #include <iostream> | |
| // ABSTRACT BASE CLASS (Shape) | |
| class Shape { | |
| protected: | |
| Vector2 position; | |
| Color color; | |
| public: | |
| Shape(Vector2 position, Color color) : position{position}, color{color} {} | |
| // We need a virtual descructor here to allow for derived class destructors: | |
| virtual ~Shape() = default; | |
| // We need a virtual method here to allow for polymorphic derived versions of draw. | |
| // Marking the virtual method as "= 0" without giving it an implementation makes | |
| // the method a "pure virtual" method. A class with more or more pure virtual | |
| // methods is an "abstract class". Abstract classes cannot be instantiated. | |
| virtual void draw() const = 0; | |
| }; | |
| // DERIVED CLASS (Circle) | |
| class Circle : public Shape { | |
| float radius; | |
| public: | |
| Circle(Vector2 position, Color color, float radius) : Shape(position, color), radius{ radius } {} | |
| ~Circle() { std::cout << "Circle Destructor\n"; } | |
| virtual void draw() const override { | |
| DrawCircleV(position, radius, color); | |
| } | |
| }; | |
| // DERIVED CLASS (Square) | |
| class Square : public Shape { | |
| float sideLength; | |
| public: | |
| Square(Vector2 position, Color color, float sideLength) : Shape(position, color), sideLength{ sideLength } {} | |
| ~Square() { std::cout << "Square Destructor\n"; } | |
| virtual void draw() const override { | |
| DrawRectangleV(position, {sideLength, sideLength}, color); | |
| } | |
| }; | |
| // A highly contrived example of polymorphism via a reference: | |
| void drawShape(Shape& s) { | |
| s.draw(); // Will call the most derived version of draw. | |
| } | |
| int main() { | |
| const int screenWidth = 800; | |
| const int screenHeight = 450; | |
| InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); | |
| SetTargetFPS(60); // Set our game to run at 60 frames-per-second | |
| std::vector<std::unique_ptr<Shape>> shapes; | |
| shapes.emplace_back(std::make_unique<Circle>(Vector2{ screenWidth / 4, screenHeight / 2 }, BLUE, 30)); | |
| shapes.emplace_back(std::make_unique<Square>(Vector2{ screenWidth / 4, screenHeight / 2 }, GREEN, 50)); | |
| while (!WindowShouldClose()) { | |
| BeginDrawing(); | |
| ClearBackground(RAYWHITE); | |
| // This will properly call the derived version of draw() | |
| // on Circle and Square objects in the shapes vector: | |
| for (const auto& s : shapes) { | |
| s->draw(); | |
| } | |
| EndDrawing(); | |
| } | |
| CloseWindow(); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment