gpt4 book ai didi

c++ - 具有非虚拟成员的类的装饰器

转载 作者:行者123 更新时间:2023-12-01 22:58:55 25 4
gpt4 key购买 nike

我尝试将装饰器模式用于通常的目的,以便能够向我的类添加功能,同时保持对类层次结构的控制。我的困难源于这样一个事实:我的类 A 有一个成员 basicVar 和一个方法 basicOp() ,它处理一些未指定的基本功能,是必需的,但在任何派生类中都不会更改。因此我将 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();}
}

继承自ADecorator的特定装饰器将重写func()以提供额外的行为。现在我的问题出现了:当使用继承自 ADecorator 的装饰器时,使用 A 接口(interface),如下所示:

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() 也声明为 virtual,问题就解决了,但是仅仅为了使用装饰器而声明一个方法 virtual 听起来就像搞砸了接口(interface)。

我非常确信这一定是由于设计错误造成的,但我无法确切地弄清楚是哪个错误以及如何解决它。也许问题在于 A 中存在数据成员,或者实际上装饰器模式仅适用于所有方法都声明为虚拟的类?

提前致谢。

最佳答案

你说得对A 有状态与装饰器的使用不兼容。你有矛盾:你说basicOp永远不会在派生类中更改,但您有一个合理的派生类 ADecorator 确实想要更改它(通过将其转发到另一个对象)。如果basicOp可以在没有任何成员变量的情况下实现(例如,它只是某些虚拟调用的包装器),内部或外部对象执行对其的调用不会有问题。

解决此问题的一种方法是分离 A 的该部分进入ConcreteA并提供 A

virtual ConcreteA& getConcrete()=0;

然后存储unique_ptr<ConcreteA>在装饰器中并实现 getConcrete适本地;任何人使用 ConcreteA 直接可以进行非虚拟调用。

关于c++ - 具有非虚拟成员的类的装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59747106/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com