fork download
  1. //Simple demo of visitor pattern
  2. //Uses raw poitner instead of smartpointers for demo purpose only
  3.  
  4. #include <iostream>
  5. #include <string>
  6. #include <map>
  7. using namespace std;
  8.  
  9. class Visitor;
  10. struct Item // items in inventory
  11. {
  12. virtual Item* clone() const=0; // duplicate an item for sotring in inventory
  13. virtual int code() const=0; // code for the map
  14. virtual void acceptVisitor(Visitor &v)=0; // allow for visitors
  15. virtual ~Item() {}
  16. };
  17.  
  18. class Book : public Item // a concrete item
  19. {
  20. int isbn; // with its specific data (a dvd has no isbn)
  21. string name;
  22. public:
  23. Book() = default;
  24. Book(const Book& b) = default;
  25. Book(int isbn, const string &name);
  26. int code() const override ; // implement item members
  27. Item* clone() const override ;
  28. void acceptVisitor(Visitor &v) override;
  29. int getIsbn() const ; // provide getters to ensure encapsulation
  30. const string& getTitle() const ;
  31. };
  32.  
  33. class Inventory
  34. {
  35. private:
  36. map<int, Item *> items;
  37. public:
  38. void addItem(const Item& i);
  39. void acceptVisitor(Visitor &v);
  40. };
  41.  
  42. class Visitor { // generic visitor. Can be used for report, for saving data, etc..
  43. public:
  44. virtual void visitInventory(Inventory *iv) = 0;
  45. virtual void visitBook(Book*) = 0;
  46. //... if you have new type of items, just add a function here
  47. virtual void visitEnd() {};
  48. };
  49.  
  50. class Report : public Visitor // FIrst report: just tell what to do fpor every class you use
  51. {
  52. private:
  53. Inventory* i;
  54. int count=0;
  55. public:
  56. Report(Inventory& i);
  57. void visitInventory(Inventory *iv);
  58. void visitBook(Book*b);
  59. void visitEnd(); // to end the report
  60. };
  61.  
  62. Book::Book(int isbn, const string &name) : isbn(isbn), name(name) {}
  63. int Book::code() const { return isbn; }
  64. Item* Book::clone() const { return new Book(*this); }
  65. void Book::acceptVisitor(Visitor &v) { v.visitBook(this); }
  66. int Book::getIsbn() const { return(isbn); }
  67. const string& Book::getTitle() const { return (name); }
  68.  
  69. void Inventory::addItem(const Item& i)
  70. {
  71. items[i.code()] =i.clone();
  72. }
  73. void Inventory::acceptVisitor(Visitor &v) {
  74. v.visitInventory(this);
  75. for (auto &x : items)
  76. x.second->acceptVisitor(v);
  77. v.visitEnd();
  78. }
  79.  
  80. Report::Report(Inventory& i) : i(&i),count(0)
  81. { i.acceptVisitor(*this); }
  82.  
  83. void Report::visitInventory(Inventory *iv) {
  84. cout << "Nice report:"<<endl;
  85. cout << "============"<<endl;
  86. }
  87. void Report::visitBook(Book*b) {
  88. cout << "Book: "<< b->getTitle() << " (ISBN "<<b->getIsbn()<<" )"<<endl;
  89. count++;
  90. }
  91. void Report::visitEnd() {
  92. cout << "Total of "<<count<<" items"<<endl;
  93. }
  94.  
  95.  
  96. int main() // CORRECT: never main(void) !!!!
  97. {
  98. Inventory i;
  99.  
  100. i.addItem(Book(1234, "Foo Bar I"));
  101. i.addItem(Book(4567, "Foo Bar II"));
  102.  
  103. Report r(i);
  104.  
  105. return 0;
  106. }
  107.  
Success #stdin #stdout 0s 3464KB
stdin
Standard input is empty
stdout
Nice report:
============
Book: Foo Bar I (ISBN 1234 )
Book: Foo Bar II (ISBN 4567 )
Total of 2 items