Sta*_*123 5 c++ pointers reference decorator
我刚刚了解了装饰器模式,并尝试编写一个使用该代码的示例。这个例子是关于饮料和一些调味品的。在装饰器内部,我有一个饮料的引用变量。可用的饮料是Decaf和Espresso。可用的调味品是Soy和Caramel。例如,如果我Decaf用多个来定义 a ,Caramel我得到的结果只是一个带有一个装饰器的 Decaf。所以定义Caramel-> Caramel->Decaf给我Caramel-> Decaf。定义Caramel-> Soy-> Caramel->Decaf工作正常。定义Caramel-> Soy-> Caramel-> Caramel->Decaf给我Caramel-> Soy-> Caramel->Decaf. 长话短说,我不能一个接一个地吃两种或多种相同类型的调味品。它们只成为一种调味品。如果我使用指针它工作正常。
编码:
#include <iostream>
//#include "Decaf.h"
//#include "Espresso.h"
//#include "SoyDecorator.h"
//#include "CaramelDecorator.h"
class Beverage
{
public:
virtual std::string GetDescription() const = 0;
virtual int GetCost() const = 0;
};
class CondimentDecorator : public Beverage
{
public:
Beverage& beverage;
CondimentDecorator(Beverage& beverage) : beverage(beverage) {}
};
class Espresso : public Beverage
{
virtual std::string GetDescription() const override
{
return "Espresso";
}
virtual int GetCost() const override
{
return 5;
}
};
class Decaf : public Beverage
{
virtual std::string GetDescription() const override
{
return "Decaf";
}
virtual int GetCost() const override
{
return 4;
}
};
class CaramelDecorator : public CondimentDecorator
{
public:
CaramelDecorator(Beverage& beverage) : CondimentDecorator(beverage) {}
virtual std::string GetDescription() const override
{
return this->beverage.GetDescription() + " with Caramel";
}
virtual int GetCost() const override
{
return this->beverage.GetCost() + 2;
}
};
class SoyDecorator : public CondimentDecorator
{
public:
SoyDecorator(Beverage& beverage) : CondimentDecorator(beverage) {}
virtual std::string GetDescription() const override
{
return this->beverage.GetDescription() + " with Soy";
}
virtual int GetCost() const override
{
return this->beverage.GetCost() + 1;
}
};
int main()
{
Decaf d;
SoyDecorator s(d);
CaramelDecorator c(s);
CaramelDecorator cc(c);
std::cout << cc.GetDescription() << std::endl;
std::cout << cc.GetCost() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Decaf with Soy with Caramel
7
// Expected:
// Decaf with Soy with Caramel with Caramel
// 9
Run Code Online (Sandbox Code Playgroud)
这是相同的代码,但使用指针并且工作正常:https : //ideone.com/7fpGSp
通过从指针切换到引用,OP 构造函数签名变得与(默认)复制构造函数非常相似。
CondimentDecorator(Beverage &beverage) : beverage(beverage) {}
Run Code Online (Sandbox Code Playgroud)
与
CondimentDecorator(const Beverage&); // generated by compiler
Run Code Online (Sandbox Code Playgroud)
首先,我认为删除复制构造函数就足够了,但编译器仍然尝试使用已删除的构造函数并提出相应的投诉,因为它不能再使用了。
最后,我能够通过提供 resp 来解决 OP 的问题。阻止使用复制构造函数的候选者。
(实际上不再需要删除复制构造函数,但我保留了它。)
class CondimentDecorator : public Beverage
{
public:
Beverage& beverage;
CondimentDecorator(Beverage &beverage) : beverage(beverage) {}
CondimentDecorator(CondimentDecorator &beverage) : beverage(beverage) {}
CondimentDecorator(const CondimentDecorator&) = delete;
};
Run Code Online (Sandbox Code Playgroud)
对于派生类也必须做同样的事情:
class CaramelDecorator : public CondimentDecorator
{
public:
CaramelDecorator(Beverage &beverage) : CondimentDecorator(beverage) {}
CaramelDecorator(CaramelDecorator &beverage) : CondimentDecorator(beverage) {}
//CaramelDecorator(const CaramelDecorator&) = delete;
virtual std::string GetDescription() const override
{
return this->beverage.GetDescription() + " with Caramel";
}
virtual int GetCost() const override
{
return this->beverage.GetCost() + 2;
}
};
Run Code Online (Sandbox Code Playgroud)
我只修复了CaramelDecoratorfor 演示,但实际上,必须对class CondimentDecorator.
OP的固定MCVE:
#include <iostream>
//#include "Decaf.h"
//#include "Espresso.h"
//#include "SoyDecorator.h"
//#include "CaramelDecorator.h"
class Beverage
{
public:
virtual std::string GetDescription() const = 0;
virtual int GetCost() const = 0;
};
class CondimentDecorator : public Beverage
{
public:
Beverage& beverage;
CondimentDecorator(Beverage &beverage) : beverage(beverage) {}
CondimentDecorator(CondimentDecorator &beverage) : beverage(beverage) {}
CondimentDecorator(const CondimentDecorator&) = delete;
};
class Espresso : public Beverage
{
virtual std::string GetDescription() const override
{
return "Espresso";
}
virtual int GetCost() const override
{
return 5;
}
};
class Decaf : public Beverage
{
virtual std::string GetDescription() const override
{
return "Decaf";
}
virtual int GetCost() const override
{
return 4;
}
};
class CaramelDecorator : public CondimentDecorator
{
public:
CaramelDecorator(Beverage &beverage) : CondimentDecorator(beverage) {}
CaramelDecorator(CaramelDecorator &beverage) : CondimentDecorator(beverage) {}
//CaramelDecorator(const CaramelDecorator&) = delete;
virtual std::string GetDescription() const override
{
return this->beverage.GetDescription() + " with Caramel";
}
virtual int GetCost() const override
{
return this->beverage.GetCost() + 2;
}
};
class SoyDecorator : public CondimentDecorator
{
public:
SoyDecorator(Beverage &beverage) : CondimentDecorator(beverage) {}
virtual std::string GetDescription() const override
{
return this->beverage.GetDescription() + " with Soy";
}
virtual int GetCost() const override
{
return this->beverage.GetCost() + 1;
}
};
int main()
{
Decaf d;
SoyDecorator s(d);
CaramelDecorator c(s);
CaramelDecorator cc(c);
std::cout << cc.GetDescription() << std::endl;
std::cout << cc.GetCost() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
输出:
CondimentDecorator(Beverage &beverage) : beverage(beverage) {}
Run Code Online (Sandbox Code Playgroud)
为什么需要额外的候选人?
CondimentDecorator源自Beverage.
因此对于:
CondimentDecorator d;
CondimentDecorator d2(d);
Run Code Online (Sandbox Code Playgroud)
编译器有两种构造选择d2:
CondimentDecorator::CondimentDecorator(Beverage &beverage)CondimentDecorator::CondimentDecorator(const CondimentDecorator&)。对于第一个,必须应用隐式强制转换,但对于复制构造函数,不需要强制转换(或者最多是 const 强制转换)。
因此,编译器更喜欢复制构造函数(不幸的是,尽管它被删除了)。
因此,必须提供另一个候选者,它需要的隐式转换与复制构造函数一样少:
CondimentDecorator::CondimentDecorator(CondimentDecorator&)。进一步阅读:过载解决方案