, хотя Пушер и Поппер не знают об элементах, Стэк знает, и это все, что важно.
Нет. Это не все, что важно для C ++, как вы можете ясно видеть, - и для этого есть все основания. То, что вы предлагаете, имеет многочисленные недостатки и поэтому не допускается. Однако существует несколько способов обойти это ограничение.
Одним из способов является использование виртуального наследования и определение абстрактного базового класса (называемого, например, Store
), который обеспечивает доступ к хранилищу, которое оба Pusher
и Popper
работают через виртуальную функцию, которая реализована в Stack
.
Однако, этот подход также имеет многочисленные проблемы и, как правило, избегается в C ++. Более идиоматический c подход использует Любопытно повторяющийся шаблон (CRTP) .
Измените Pusher
и Popper
на шаблоны классов, которые принимают Stack
class в качестве аргумента шаблона:
template <typename T>
class Pusher {
public:
void Push(int value) {
// Simulates internal logic of pushing a value.
T::elements(*this).push_back(value);
}
};
template <typename T>
class Popper {
public:
int Pop() {
// Simulates internal logic of popping a value.
int popped_value = T::elements(*this).back();
T::elements(*this).pop_back();
return popped_value;
}
};
class Stack: public Pusher<Stack>, public Popper<Stack> {
public:
template <typename T>
static std::vector<int>& elements(T& s) {
return static_cast<Stack&>(s).elements_;
}
private:
std::vector<int> elements_;
};
Нет необходимости говорить, что это все еще довольно запутанно, потому что ваша зависимость от данных инвертирована. Тщательно продумайте, какие зависимости вам нужны для ваших характеристик и как они полезны.
Еще одна реализация, близкая к 1032 * контейнерному адаптеру стандартной библиотеки, предназначена для реализации. Pusher
и Popper
как декораторы : то есть они наследуются от Stack
, а не наоборот. Это может быть полезно, но только если вы измените имена: очевидно, что иметь класс Stack
, который не выполняет ни push, ни popping, не имеет смысла. Снова посмотрите на интерфейс класса адаптера std::stack
для вдохновения.