Как работает шаблон декоратора в C++

Надеюсь, это не дубликат, и прошу прощения за мой неидеальный английский.

Я пытаюсь понять, как именно работает шаблон декоратора в C++.

Я использую реализацию это, найденную в Интернете, и дизайн мне понятен.

Я не могу понять, как это работает технически.

Когда я создаю новый объект и украшаю его, например:

AbstractNPC *goblin1= new Elite(new Shaman(new NPC("Goblin")));

Тип гоблина1 будет Элита, Шаман, NPC что ли?

И как функция render () «берет» реализацию других классов и использует их вместе?

Я ожидал, что когда я вызываю render (), я рекурсивно вызываю функции из других классов декораторов, используя эту инструкцию:

NPCDecorator::render();

По-прежнему для меня это не имеет смысла.

Как и почему это работает?

N.b. этот пример плохой C++. new должен отсутствовать в нормальном коде и всегда должен совпадать с delete там, где он присутствует.

Caleth 22.05.2018 16:15

@PiotrNycz Да, я знаком с этими концепциями, но, очевидно, недостаточно. Я буду читать эти страницы внимательнее, спасибо.

Domenico Paolicelli 22.05.2018 16:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
323
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Тип уместнымgoblin1 прямо здесь в объявлении, AbstractNPC *.

NPCDecoratorорудия этого абстрактного класса, удерживая экземпляр Другой этого абстрактного класса. В выражении new Elite(new Shaman(new NPC("Goblin"))) есть экземпляры триAbstractNPC, два декоратора и «нормальный» экземпляр.

Когда виртуальный вызов render поступает в первый декоратор, он выполняет свои действия, а затем вызывает его базовые классы render, которые просто делегируются декорированному члену npc.

У вас будет стек вызовов, например:

Elite::render
{
    // this == Elite * @ 0x12345678
    cout << "Elite ";
    NPCDecorator::render
    {
        Shaman::render
        {
            // this == Shaman * @ 0x56781234
            cout << "Shaman ";
            NPCDecorator::render
            {
                NPC::render
                {
                    // this == NPC * @ 0x78563412
                    cout << name; // "Goblin"
                }
            }
        }
    }
}

Уао, это здорово. Спасибо, Калет, этот ответ действительно ясен! Что касается вашего комментария о новом, что я должен использовать вместо нового?

Domenico Paolicelli 22.05.2018 16:27

Переключите AbstractNPC * на std::unique_ptr<AbstractNPC> и используйте, например, std::unique_ptr<AbstractNPC> goblin1 = std::make_unique<Elite>(std::make_unique<Shaman>(std::make_u‌​nique("Goblin")));

Caleth 22.05.2018 16:30

Другие вопросы по теме