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 turn: 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).

Previous: Abstract classes Next: Virtual destructors