C/C++ Arena

Step 4 of 9

Polymorphic containers

To hold different derived types in one container, you can't store the objects themselves: a std::vector<Shape> would only have room for the base part, and an abstract base can't be stored at all. Instead, store pointers to the base, and let virtual calls reach each real object. With std::unique_ptr, the vector owns the objects and nothing leaks.

#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

class Plan {
public:
    virtual double monthly(int users) const = 0;
    virtual ~Plan() = default;
};

class Flat : public Plan {
public:
    explicit Flat(double price) : price_(price) {}
    double monthly(int) const override { return price_; }
private:
    double price_;
};

class PerSeat : public Plan {
public:
    double monthly(int users) const override {
        return users <= 5 ? users * 8.0 : 40 + (users - 5) * 6.0;   // cheaper after 5 seats
    }
};

int main() {
    std::vector<std::unique_ptr<Plan>> plans;
    plans.push_back(std::make_unique<Flat>(99));
    plans.push_back(std::make_unique<PerSeat>());

    for (int users : {3, 12}) {
        double cheapest = 1e9;
        for (const auto& p : plans) cheapest = std::min(cheapest, p->monthly(users));
        std::cout << users << " users: best price " << cheapest << "\n";
    }
}
3 users: best price 24
12 users: best price 82

How it works

Your task: shotgun damage

"80 on the first hit, 20 for each hit after" means hits of 0 gives 0, 1 gives 80, 3 gives 80 + 20 + 20. Handle 0 hits separately. total_damage is then a loop that adds w->damage(hits) for every weapon.

Your task

Write int total_damage(const std::vector<std::unique_ptr<Weapon>>& ws, int hits) that sums damage(hits) across all weapons, and implement Pistol (25 per hit) and Shotgun (80 on the first hit, 20 for each hit after).

Challenge 2

Write effects that change a player's hp: Poison takes 10, Heal adds 25 but never goes above 100, and Shield changes nothing. Then write int apply_all(const std::vector<std::unique_ptr<Effect>>& effects, int hp) that applies them in order and never lets hp go below 0.

Challenge 3

Write a factory: std::unique_ptr<Weapon> make_weapon(const std::string& name) returns a new Pistol for "pistol", a new Shotgun for "shotgun", and nullptr otherwise. Implement both classes (pistol 25 per hit; shotgun 80 for the first hit and 20 for each after), then int total_for(const std::vector<std::string>& names, int hits), which skips unknown names.

Previous: Abstract classes Next: Virtual destructors