Надеюсь, это не дубликат, и прошу прощения за мой неидеальный английский.
Я пытаюсь понять, как именно работает шаблон декоратора в C++.
Я использую реализацию это, найденную в Интернете, и дизайн мне понятен.
Я не могу понять, как это работает технически.
Когда я создаю новый объект и украшаю его, например:
AbstractNPC *goblin1= new Elite(new Shaman(new NPC("Goblin")));
Тип гоблина1 будет Элита, Шаман, NPC что ли?
И как функция render () «берет» реализацию других классов и использует их вместе?
Я ожидал, что когда я вызываю render (), я рекурсивно вызываю функции из других классов декораторов, используя эту инструкцию:
NPCDecorator::render();
По-прежнему для меня это не имеет смысла.
Как и почему это работает?
N.b. этот пример плохой C++. new должен отсутствовать в нормальном коде и всегда должен совпадать с delete там, где он присутствует.
@PiotrNycz Да, я знаком с этими концепциями, но, очевидно, недостаточно. Я буду читать эти страницы внимательнее, спасибо.





Тип уместным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"
}
}
}
}
}
Уао, это здорово. Спасибо, Калет, этот ответ действительно ясен! Что касается вашего комментария о новом, что я должен использовать вместо нового?
Переключите AbstractNPC * на std::unique_ptr<AbstractNPC> и используйте, например, std::unique_ptr<AbstractNPC> goblin1 = std::make_unique<Elite>(std::make_unique<Shaman>(std::make_unique("Goblin")));
Вы знакомы с en.cppreference.com/w/cpp/language/object#Polymorphic_object s и en.cppreference.com/w/cpp/language/member_functions?