Я пытаюсь использовать шаблон декоратора для обычной цели, чтобы иметь возможность добавлять функциональные возможности в мой класс, сохраняя при этом контроль над иерархией классов. Моя трудность связана с тем фактом, что в моем классе A
есть член basicVar
и метод basicOp()
, который имеет дело с некоторыми неуказанными базовыми функциями c, которые необходимы, но никогда не будут изменены в любом производном классе. По этой причине я объявляю A как:
class A {
public:
virtual void func() { /* Some default implementation */}
void basicOp() { /* some basic operation on basicVar*/}
private:
int basicVar;
}
Таким образом, производные классы не должны реализовывать basicOp()
, а вызовы basicOp()
не связаны с накладными расходами виртуального вызова. Затем я реализую базовый класс декоратора следующим образом:
class ADecorator: public A{
protected:
std::unique_ptr<A> _a;
public:
ADecorator(std::unique_ptr<A> a): _a(std::move(a)){}
void func(){ _a->func(); }
void basicOp(){ _a->basicOp();}
}
Спецификаторы c, наследующие от ADecorator
, будут переопределять func()
для обеспечения дополнительного поведения. Теперь возникает моя проблема: при использовании декоратора, унаследованного от ADecorator
с использованием интерфейса A
, подобного следующему:
std::unique_ptr<A> dec = std::make_unique<Decorator>(std::make_unique<A>());
dec->basicOp();
, вызываемый метод будет A::basicOp()
, который работает на dec.basicVar
вместо ADecorator::basicOp()
который действует на элемент dec._a.basicVar
объекта, обернутого декоратором. Это не произойдет с func()
, поскольку он виртуальный. Объявляя также basicOp()
как виртуальный, проблема решается, но объявление метода виртуальным просто для того, чтобы сделать возможным использование декораторов, звучит как привинчивание интерфейса.
Я совершенно уверен, что это должно проистекать из дизайна ошибка, но я не могу точно понять, какой и как ее решить. Может быть, проблема заключается в наличии члена данных в A
или в том факте, что эффективно шаблон декоратора предназначен для использования только с классами со всеми методами, объявленными как виртуальные?
Заранее спасибо.