#include #include #include #include #include #include #include #include class AbstractVisitor; class Ammunition { public: Ammunition(size_t amount) : _amount(amount) {} virtual ~Ammunition() = default; virtual void accept(const AbstractVisitor&) = 0; size_t amount() const { return _amount; } private: size_t _amount = 0; }; class RoundShot; class ChainShot; class GrapeShot; class AbstractVisitor { protected: // Can be only use by derived class virtual ~AbstractVisitor() = default; }; template class Visitor { public: virtual void visit(const T& shot) const = 0; protected: virtual ~Visitor() = default; }; class DamageVisitor : public AbstractVisitor, public Visitor, public Visitor, public Visitor { public: void visit(const RoundShot& shot) const override { std::cout << "Round shot make 20 damages\n"; } void visit(const ChainShot& shot) const override { std::cout << "Chain shot make 30 damages\n"; } void visit(const GrapeShot& shot) const override { std::cout << "Grape shot make 40 damages\n"; } }; class SoundVisitor : public AbstractVisitor, public Visitor, public Visitor, public Visitor { public: void visit(const RoundShot& shot) const override { std::cout << "Fiuuuuuuuu Bam!\n"; } void visit(const ChainShot& shot) const override { std::cout << "Fiuuuuuuuuuuu Bam bam!\n"; } void visit(const GrapeShot& shot) const override { std::cout << "Fiuuuuuuuuuuu Bam bam bam bam bam!\n"; } }; class RoundShot : public Ammunition { public: using Ammunition::Ammunition; void accept(const AbstractVisitor& visitor) { if (const auto* v = dynamic_cast*>(&visitor)) { v->visit(*this); } } }; class ChainShot : public Ammunition { public: using Ammunition::Ammunition; void accept(const AbstractVisitor& visitor) { if (const auto* v = dynamic_cast*>(&visitor)) { v->visit(*this); } } }; class GrapeShot : public Ammunition { public: using Ammunition::Ammunition; void accept(const AbstractVisitor& visitor) { if (const auto* v = dynamic_cast*>(&visitor)) { v->visit(*this); } } }; int main() { std::unique_ptr grapeShot = std::make_unique(100); SoundVisitor soundVisitor; DamageVisitor damageVisitor; grapeShot->accept(soundVisitor); grapeShot->accept(damageVisitor); }