При переключении с указателей на ссылки сигнатура конструктора OP становится очень похожей на конструктор копирования (по умолчанию).
CondimentDecorator(Beverage &beverage) : beverage(beverage) {}
против
CondimentDecorator(const Beverage&); // generated by compiler
Сначала я предположил удалить конструктора копирования было бы достаточно, но компилятор все еще пытается использовать удаленный конструктор с соответствующей жалобой, поскольку он больше не может.
Наконец, я смог решить проблему OP с предоставлением соотв. кандидаты, которые не позволяют использовать конструктор копирования.
(Удаление конструктора копирования больше не требовалось, но я оставил его.)
class CondimentDecorator : public Beverage
{
public:
Beverage& beverage;
CondimentDecorator(Beverage &beverage) : beverage(beverage) {}
CondimentDecorator(CondimentDecorator &beverage) : beverage(beverage) {}
CondimentDecorator(const CondimentDecorator&) = delete;
};
То же самое должно быть сделано для производных классов :
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;
}
};
Я исправил только CaramelDecorator
для демонстрации, но на самом деле это должно быть сделано для всех производных классов class CondimentDecorator
.
Фиксированный MCVE для OP:
#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;
}
Выход:
Decaf with Soy with Caramel with Caramel
9
Live демо на coliru
Почему дополнительные нужны кандидаты?
CondimentDecorator
является производным от Beverage
.
Итак, для:
CondimentDecorator d;
CondimentDecorator d2(d);
у компилятора есть два варианта построения d2
:
- пользовательский конструктор
CondimentDecorator::CondimentDecorator(Beverage &beverage)
- (по умолчанию) конструктор копирования
CondimentDecorator::CondimentDecorator(const CondimentDecorator&)
.
Для первого - неявное приведение должен быть применен, но для конструктора копирования нет необходимости в преобразовании (или, самое большее, в преобразование const).
Следовательно, компилятор предпочитает конструктор копирования (к сожалению, даже, хотя он удален).
Итак, необходимо предоставить другого кандидата, который требует не менее явных приведений, таких как конструктор копирования:
другой пользовательский конструктор
CondimentDecorator::CondimentDecorator(CondimentDecorator&)
.
Дополнительная информация: Разрешение перегрузки