Я вегетарианец, поэтому предположим, что у нас есть овощи:
class Vegetable {}; // base class for vegetables
class Tomato : public Vegetable {};
class Potato : public Vegetable {};
class Carrot : public Vegetable {};
class Broccoli : public Vegetable {};
И предположим, что мы хотим готовить с ними еду:
class Meal {}; // base class for meals
class Soup : public Meal {
...
Soup(Vegetable *veg1, Vegetable *veg2) : veg1(veg1), veg2(veg2) {};
};
class Salad : public Meal {
...
Salad(Vegetable *veg1, Vegetable *veg2, Vegetable *veg3) : veg1(veg1), veg2(veg2), veg3(veg3) {};
};
class VeggieBurger : public Meal {
...
VeggieBurger(Vegetable *veg) : veg(veg) {};
};
Теперь мы хотели бы определить различные блюда с различными овощными комбинациями в поваренной книге:
std::vector<Meal *> cookbook;
cookbook.push_back(new Soup(new Tomato, new Potato));
cookbook.push_back(new Soup(new Potato, new Broccoli));
cookbook.push_back(new Salad(new Tomato, new Carrot, new Broccoli));
cookbook.push_back(new Salad(new Tomato, new Potato, new Tomato));
cookbook.push_back(new Salad(new Broccoli, new Potato, new Carrot));
cookbook.push_back(new VeggieBurger(new Potato));
// many more meals...
Итак, мы создаем много маленьких объектов в куче, которые собираются вместе с помощью аргументов конструктора и помещаются в std :: vector во время выполнения. Очевидно, что недостатком этого дизайна является то, что нам нужно самим управлять памятью, удалять объекты «Овощ» в деструкторе наших блюд и удалять наши блюда из кулинарной книги где-нибудь, когда они выходят за рамки.
Таким образом, возможный выбор дизайна - использовать умные указатели, чтобы нести бремя управления памятью для наших блюд и овощей.
Но мне интересно, можно ли составить кулинарную книгу во время компиляции, может быть, с помощью какой-то магии шаблонов? Кулинарная книга не обязательно должна быть std :: vector, но мы все же хотели бы иметь возможность перебирать ее, получать объекты Meal и вызывать функции-члены в составленной еде. Есть ли лучшие способы сделать это?