Как декорировать объекты в одной строке кода, используя шаблон декоратора в C ++?

Я учу шаблон декоратора от Книга Head First Design Patterns , и вот что я кодировал (C ++), чтобы заставить шаблон работать:

#include <iostream>class AbstractType
{
public:
virtual double value() const = 0;
};class FirstConcreteType
:
public AbstractType
{
public:
double value() const
{
return 1;
}
};

class SecondConcreteType
:
public AbstractType
{
public:
double value() const
{
return 2;
}
};

class DecoratorType
:
public AbstractType
{
const AbstractType* decoratedObject_;

public:

DecoratorType(const AbstractType& abstractObject)
:
decoratedObject_(&abstractObject)
{}

DecoratorType(const DecoratorType& decoratorObject)
:
decoratedObject_(&decoratorObject)
{}

virtual double value() const = 0;

const AbstractType& getObject() const
{
return *decoratedObject_;
}
};

class FirstDecoratorType
:
public DecoratorType
{
public:
FirstDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}

FirstDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}

double value() const
{
const AbstractType& object = getObject();

return 1 + object.value();
}
};

class SecondDecoratorType
:
public DecoratorType
{
public:
SecondDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}

SecondDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}

double value() const
{
const AbstractType& object = getObject();

return 2 + object.value();
}
};

using namespace std;

int main()
{
// When I decorate sequentially, it works fine

SecondConcreteType secondConc;

FirstDecoratorType firstDec(secondConc);
cout << firstDec.value() << endl;

SecondDecoratorType secondDec(firstDec);
cout << secondDec.value() << endl;

FirstDecoratorType firstDecSecond (secondDec);
cout << firstDecSecond.value() << endl;

// Decorating in a single line, messes things up, since there is no
// constructor taking the value argument defined.
//FirstDecoratorType firstDynamicDec (SecondConcreteType());
//cout << firstDynamicDec.value() << endl;

return 0;
};

В основной программе сначала должен быть создан объект этого ConcreteType, а затем он оформляется с использованием композиции указателя на AbstractType (внутри DecoratorType). Это работает нормально, если я создаю конкретные объекты и создаю новые украшенные объекты один за другим.

Что мне нужно сделать, чтобы DecoratorType мог декорировать объекты, используя композицию в одной строке кода (закомментированная строка в примере кода)? Может ли что-то подобное быть полезным в «реальном мире»? У меня (очевидно) нет большого опыта использования шаблонов проектирования … поэтому мне трудно понять, к какой функциональности я должен стремиться.

РЕДАКТИРОВАТЬ:

Вот версия, работающая с основными указателями (valgrind не показывает утечки памяти и утверждает, что утечки памяти невозможны):

#include <iostream>class AbstractType
{
public:
virtual double value() const = 0;

virtual ~AbstractType() {};
};

class FirstConcreteType
:
public AbstractType
{
public:
double value() const
{
return 1;
}
};

class SecondConcreteType
:
public AbstractType
{
public:
double value() const
{
return 2;
}
};

class DecoratorType
:
public AbstractType
{
const AbstractType* decoratedObject_;
bool own_;

public:

DecoratorType(const AbstractType& abstractObject)
:
decoratedObject_(&abstractObject),
own_(false)
{}

DecoratorType(const DecoratorType& decoratorObject)
:
decoratedObject_(&decoratorObject),
own_(false)

{}

DecoratorType (AbstractType* abstractPtr)
:
decoratedObject_(abstractPtr),
own_(true)
{}

DecoratorType (DecoratorType* decoratorPtr)
:
decoratedObject_(decoratorPtr),
own_(true)
{}

virtual ~DecoratorType()
{
if (own_)
{
delete decoratedObject_;
decoratedObject_ = 0;
}
}

virtual double value() const = 0;

const AbstractType& getObject() const
{
return *decoratedObject_;
}
};

class FirstDecoratorType
:
public DecoratorType
{
public:
FirstDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}

FirstDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}

FirstDecoratorType (AbstractType* abstractPtr)
:
DecoratorType(abstractPtr)
{}

FirstDecoratorType (FirstDecoratorType* decoratorPtr)
:
DecoratorType(decoratorPtr)
{}double value() const
{
const AbstractType& object = getObject();

return 1 + object.value();
}
};

class SecondDecoratorType
:
public DecoratorType
{
public:
SecondDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}

SecondDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}

SecondDecoratorType (AbstractType* abstractPtr)
:
DecoratorType(abstractPtr)
{}

SecondDecoratorType (SecondDecoratorType* decoratorPtr)
:
DecoratorType(decoratorPtr)
{}

double value() const
{
const AbstractType& object = getObject();

return 2 + object.value();
}
};

using namespace std;

int main()
{
// When I decorate sequentially, it works fine

SecondConcreteType secondConc;

FirstDecoratorType firstDec(secondConc);
cout << firstDec.value() << endl;

SecondDecoratorType secondDec(firstDec);
cout << secondDec.value() << endl;

FirstDecoratorType firstDecSecond (secondDec);
cout << firstDecSecond.value() << endl;

// Decorating in a single line, messes things up, since there is no
// constructor taking the value argument defined.
FirstDecoratorType firstDynamicDec (new SecondDecoratorType (
new FirstDecoratorType (new SecondConcreteType())));

cout << firstDynamicDec.value() << endl;

return 0;
};

0

Решение

FirstDecoratorType firstDynamicDec (SecondConcreteType());

Проблема в том, что он НЕ определяет объект. Вместо этого это объявляет функция. Ищу наиболее раздражающий-синтаксический анализ в C ++ на этом сайте вы получите много тем.

Краткое объяснение: имя функции firstDynamicDec чей тип возврата FirstDecoratorType и он принимает параметр, который снова является функцией, возвращающей SecondConcreteType и не принимая никаких аргументов.

4

Другие решения

Первая проблема заключается в том, что

FirstDecoratorType firstDynamicDec (SecondConcreteType());

не объявляет объект вообще, но функцию. Это называется самый неприятный разбор C ++.

Но даже когда вы работаете над этим, у вас есть проблема с временными объектами (такими как созданные SecondConcreteTpe()) существуют только до конца выражения, поэтому указатель внутри FirstDecoratorType будет недействительным, прежде чем вы сможете сделать что-нибудь полезное с ним.
Вы можете решить эту проблему, используя умные указатели для удержания декорированного типа в декораторе (например, std::unique_ptr). Это делает декоратора ответственным за очистку декорированного шрифта.

1

По вопросам рекламы [email protected]