Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
 Аватар для Nishen
1358 / 856 / 366
Регистрация: 26.02.2015
Сообщений: 3,814

Паттерны проектирования

30.07.2020, 18:06. Показов 3084. Ответов 21

Студворк — интернет-сервис помощи студентам
Добрый день! Начал читать книгу GoF, сами паттерны мне пока что понятны, но есть один вопросик, связанный с очисткой всего того, что мы создаем. Возьмем пример с лабиринтом из части о порождающих паттернах (код ниже).

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
enum class Direction {
 
    north = 0,
    east,
    south,
    west
 
};
 
class MapSite {
 
public:
    virtual void enter() = 0;
 
};
 
class Room : public MapSite {
 
public:
    Room(int roomNumber) :
        sides_(), roomNumber_(roomNumber) { }
 
    MapSite* getSide(Direction direction) const {
 
        return sides_[static_cast<int>(direction)];
 
    }
 
    void setSide(Direction direction, MapSite* side) {
 
        sides_[static_cast<int>(direction)] = side;
 
    }
 
    int getRoomNumber() const {
 
        return roomNumber_;
 
    }
 
    virtual void enter() override { }
 
private:
    MapSite* sides_[4];
    int roomNumber_;
 
};
 
class Wall : public MapSite {
 
public:
    Wall() { }
 
    virtual void enter() override { }
 
};
 
class Door : public MapSite {
 
public:
    Door(Room* from = 0, Room* to = 0) :
        from_(from), to_(to), isOpen_(false) { }
 
    virtual void enter() override { }
 
    Room* otherSideFrom(Room* room) { 
        
        //??? 
 
    }
 
private:
    Room* from_;
    Room* to_;
    bool isOpen_;
 
};
 
class Maze {
 
public:
    Maze() { }
 
    void addRoom(Room* room) {
 
        rooms_.push_back(room);
 
    }
 
    Room* getRoomByNumber(int number) const {
 
        for (const auto& room : rooms_) {
 
            if (room->getRoomNumber() == number)
                return room;
 
        }
 
        return nullptr;
 
    }
 
private:
    std::vector<Room*> rooms_;
 
};
 
class MazeGame {
 
public:
    Maze* createMaze() {
 
        Maze* aMaze = new Maze;
        Room* r1 = new Room(1);
        Room* r2 = new Room(2);
        Door* theDoor = new Door(r1, r2);
 
        aMaze->addRoom(r1);
        aMaze->addRoom(r2);
 
        r1->setSide(Direction::north, new Wall);
        r1->setSide(Direction::east, theDoor);
        r1->setSide(Direction::south, new Wall);
        r1->setSide(Direction::west, new Wall);
 
        r2->setSide(Direction::north, new Wall);
        r2->setSide(Direction::east, new Wall);
        r2->setSide(Direction::south, new Wall);
        r2->setSide(Direction::west, theDoor);
 
        return aMaze;
 
    }
 
};
 
int main() {
 
    MazeGame game;
 
    Maze* maze = game.createMaze();
 
    return 0;
 
}
Вот создаем мы комнаты, стены и двери на стороне клиента. А как это все дело удалять? Да, можно было бы написать деструктор в классе Maze, даже с необычной логикой (чтобы дверь дважды не удалять), но ведь выделяли память мы в MazeGame, т.е. на стороне клиентского кода, а удалять ее будем на стороне, например, библиотки? Получается, что new и delete настолько далеко друг от друга становятся, что страшно. Можно было бы в MazeGame все чистить, но у нас класс Maze отвечает за хранение всех созданных комнат, логичнее было бы доверить ему и очистку этих самых комнат. Может быть есть какие-то best practice по разработке интерфейсов?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.07.2020, 18:06
Ответы с готовыми решениями:

Паттерны проектирования (Фабрики)
Добрый вечер. Есть игра &quot;Морской бой&quot; из учебника Павловской Т.А . Задача: добавить в ней какой-либо шаблон проектирования. Я...

Паттерны проектирования. Где найти диаграммы?
Здравствуйте. Есть такое понятие как Паттерны проектирования (GOF). Вот список этих паттернов: Наблюдатель (Observer) Итератор...

С чего начать изучать паттерны проектирования?
С чего лучше всего начать изучение паттернов проектирования новичку? Большинство говорят, что надо читать классику - банду четырех. С чего...

21
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,686
30.07.2020, 18:54
А что Вас смущает? После добавления комнаты в лабиринт, он (лабиринт) стал владельцем объекта, ему и удалять.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
30.07.2020, 19:34
Цитата Сообщение от Nishen Посмотреть сообщение
А как это все дело удалять?
есть такой железобетонный принцип: кто память выделял, тот и должен её удалять.

Цитата Сообщение от Nishen Посмотреть сообщение
выделяли память мы в MazeGame, т.е. на стороне клиентского кода, а удалять ее будем на стороне, например, библиотки?
так нельзя делать. категорически.

дело в том, что все эти new/delete работают с т.н. "менеджером памяти".
какой именно используется менеджер - это зависит от crt (с++ библиотека времени выполнения)

если твоя библиотека и приложение используют различный crt
(такое может быть когда приложение линкуется с dll, например)
тогда нет никаких гарантий что используемые менеджеры памяти будут совместимы.

и если память выделит один менеджер (например, менеджер приложения),
а удалять будет другой (менеджер библиотеки),
тогда последствия не определены.
скорее всего будет краш из-за попытки удалить чужую память.

Цитата Сообщение от Nishen Посмотреть сообщение
Может быть есть какие-то best practice по разработке интерфейсов?
открой для себя смартпоинтеры

Цитата Сообщение от Annemesski Посмотреть сообщение
А что Вас смущает? После добавления комнаты в лабиринт, он (лабиринт) стал владельцем объекта, ему и удалять.
а тебя не смущает, что твой лабиринт должен удалять память которую он не выделял?
тебя совсем не смущает, что ты вешаешь на класс ответственность,
которая не имеет никакого отношения к его работе?

вот как ты будешь в классе лабиринта контролировать как правильно удалять память,
которая выделяется хрен-знает-как вообще в отдельном модуле?


если память выделялась в соседней библиотеке,
то безопасно удалить её можно только и только на стороне этой же библиотеки.
1
 Аватар для Annemesski
2670 / 1333 / 479
Регистрация: 08.11.2016
Сообщений: 3,686
30.07.2020, 20:03
hoggy, убедил, правило которого стоит придерживаться, тогда что? Держать в комнате счетчик ссылок и уничтожать по обнулении?
0
19495 / 10100 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
30.07.2020, 20:51
Annemesski,
1) можно не отдавать владение на сторону
2) можно предоставлять правильные функции удаления, которыми другая сторона может воспользоваться
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
30.07.2020, 21:03
Цитата Сообщение от Nishen Посмотреть сообщение
C++
1
2
3
4
class MapSite {
public:
 virtual void enter() = 0;
};
виртуальный деструктор не повредил бы) То есть, необходим.

Добавлено через 9 минут
Цитата Сообщение от Nishen Посмотреть сообщение
std::vector<Room*> rooms_;
А тут смарт пойнтер - shared_ptr<Room>, например, подошёл бы (или придётся руками делетить). :-)
1
 Аватар для Nishen
1358 / 856 / 366
Регистрация: 26.02.2015
Сообщений: 3,814
30.07.2020, 22:36  [ТС]
https://habr.com/ru/post/427281/

Добавлено через 1 минуту
Цитата Сообщение от Annemesski Посмотреть сообщение
А что Вас смущает? После добавления комнаты в лабиринт, он (лабиринт) стал владельцем объекта, ему и удалять.
Смущает то, что класс Maze может оказаться одним из классов библиотеки. И мы будем создавать элементы лабиринта и добавлять их в лабиринт в клиентсом коде, а удалять их на стороне библиотеки? Я не знал, почему это не правильно, до ответа hoggy, но это даже кажется немного неправильным по логике.

Добавлено через 1 минуту
Цитата Сообщение от IGPIGP Посмотреть сообщение
виртуальный деструктор не повредил бы) То есть, необходим.
Спасибо за замечание! :-) Просто опустил в примере, но согласен, практика это плохая.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
30.07.2020, 22:41
Цитата Сообщение от Nishen Посмотреть сообщение
Спасибо за замечание! :-) Просто опустил в примере, но согласен, практика это плохая.
В контексте вопроса это связано с самой его сутью. Когда у вас есть: vector<shared_ptr<MapSite>> mapSitesPtrs всё работает в поле RAII как для простых объектов на стеке (в смысле автоматики только, разумеется). В этом плане, вопрос о том кто будет убирать - риторика.
Базовые указатели указывают на объекты конкретных типов-наследников и вам незачем знать кто и как их удаляет.
1
19495 / 10100 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
30.07.2020, 23:03
Nishen, если владение передавалось через границу модуля, то умные указатели без правильного deleter`а также могут испортить все дело, как и ручной delete, при наличии двух менеджеров памяти.

Вот тут у меня есть пример, как этого избегать.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
31.07.2020, 01:02
Nishen, интерфейсы это широкая тема. В самом общем смысле весь мир интерфейс и люди в нём интерфейсы.
А конкретный лабиринт, это граф, но в игровом контексте. И контекст задаёт ... контекст. То есть, если лабиринт виден весь и сразу, то жизненный цикд - весь игровой сеанс. Если виден фрагмент (сверху) то имеет смыл разделять время жизни видимых и не видимых объектов. А если видны лишь объекты доступные из одной комнаты, но высоко детализировано и прорисовано (ресурсоёмко) то кольцо сужается еще сильнее. В этом контексте можно придумать разные вещи. Мне приходит на ум паттерн состояние. То есть, есть мапа -примитивно сгенерированный лабиринт (частично или полностью, тоже зависит от контекста). В нем есть узел в котором находится игрок. Узел в фокусе. Этот узел создает окружающие узлы согласно карте. То есть, он выделяет все ресурсы для детального представления. А как только игрок активизирует (фокусирует) другой узел, бывший фокус освобождает непересекающиеся ресурсы. Новый это объект окружения старого фокуса и был создан заблаговременно, но он должен создать недостающие объекты своего окружения (чтобы они были готовы принять следующий фокус). Это может напоминать пчелу перелетающую с ромашки на ромашку. Только срединки ромашек - лепестки соседей. Всё это абсолютно непонятно, но сделать можно.
Я хотел сказать, что вопрос жизненного цикла плотно связан игровым контекстом. Это может подсказать оптимальную или приемлемую модель владения.
В простом автомате где стэйты -узлы не требующие ресурсов и времени, каждое состояние создайт новое, - передаёт фокус и удаляет себя при помощи очень страшного delete this . Тут и смартов не требуется. Но в "с ромашки на ромашку" тоже так можно.
http://cpp-reference.ru/patter... rns/state/
C++
1
2
3
4
5
6
void ON::off(Machine *m)
{
  cout << "   going from ON to OFF";
  m->setCurrent(new OFF());
  delete this;// :)
}
Тут убивает не тот кто породил. Но тем чем породил. То есть, частично сохраняется естественность процесса.
1
 Аватар для Nishen
1358 / 856 / 366
Регистрация: 26.02.2015
Сообщений: 3,814
04.08.2020, 11:56  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include <array>
#include <iostream>
#include <memory>
#include <vector>
 
enum class Direction {
 
    north, east, south, west
 
};
 
class MapSite {
 
public:
    virtual ~MapSite() { }
    virtual void enter() = 0;
 
};
 
class Room : public MapSite {
 
public:
    Room(int roomNumber) :
        sides_(), roomNumber_(roomNumber) { }
 
    ~Room() {
 
        std::cout << "Deleting room with number " 
            << roomNumber_ << '\n';
 
    }
 
    MapSite* getSide(Direction direction) const {
 
        return sides_[static_cast<int>(direction)].get();
 
    }
    
    void setSide(Direction direction, MapSite* site) {
 
        sides_[static_cast<int>(direction)] =
                std::make_shared<MapSite>(site);
 
    }
 
    int getRoomNumber() const {
 
        return roomNumber_;
 
    }
 
    virtual void enter() override { }
 
private:
    std::array<std::shared_ptr<MapSite>, 4> sides_;
    int roomNumber_;
 
};
 
class Wall : public MapSite {
 
public:
    Wall() { }
 
    ~Wall() {
 
        std::cout << "Deleting the wall\n";
 
    }
 
    virtual void enter() override { }
 
};
 
class Door : public MapSite {
 
public:
    Door(Room* from = nullptr, Room* to = nullptr) :
        from_(from), to_(to), isOpen_(false) { }
 
    ~Door() {
 
        std::cout << "Deleting the door\n";
 
    }
 
    virtual void enter() override { }
 
    Room* otherSideFrom(Room* room) {
 
        if (room == from_)
            return to_;
 
        if (room == to_)
            return from_;
 
        return nullptr;
 
    }
 
private:
    Room* from_;
    Room* to_;
    bool isOpen_;
 
};
 
class Maze {
 
public:
    Maze() :
        rooms_() { }
 
    void addRoom(Room* room) {
 
        rooms_.emplace_back(room);
 
    }
 
    Room* getRoomByNumber(int roomNumber) const {
 
        for (const auto& room : rooms_) {
 
            if (room->getRoomNumber() == roomNumber)
                return room.get();
 
        }
 
        return nullptr;
 
    }
 
private:
    std::vector<std::shared_ptr<Room>> rooms_;
 
};
 
class MazeGame {
 
public:
    Maze* createMaze() {
 
        Maze* maze = new Maze;
        Room* r1 = new Room(1);
        Room* r2 = new Room(2);
        Door* theDoor = new Door(r1, r2);
 
        maze->addRoom(r1);
        maze->addRoom(r2);
 
        r1->setSide(Direction::north, new Wall);
        r1->setSide(Direction::east, theDoor);
        r1->setSide(Direction::south, new Wall);
        r1->setSide(Direction::west, new Wall);
 
        r2->setSide(Direction::north, new Wall);
        r2->setSide(Direction::east, new Wall);
        r2->setSide(Direction::south, new Wall);
        r2->setSide(Direction::west, theDoor);
 
        return maze;
 
    }
 
};
 
int main() {
 
    MazeGame game;
    Maze* maze = game.createMaze();
 
    delete maze;
 
    return 0;
 
}
Как теперь переписать функцию Room::setSide, ведь я не могу создавать объекты класс MapSite и мой компилятор ругается на это: 'MapSite': cannot instantiate abstract class.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
04.08.2020, 12:08
Цитата Сообщение от Nishen Посмотреть сообщение
Как теперь переписать функцию Room::setSide, ведь я не могу создавать объекты класс MapSite и мой компилятор ругается на это: 'MapSite': cannot instantiate abstract class.
Можно умные указатели мувить. Сначала инициализируете указатель базового MapSite * нужным наследником созданным в куче, а потом перемещаете указатель в массив/вектор. Вектор нулевых можно создать без создания объектов. А можно empace_back использовать. Главное создать простой указатель и обернуть в умный. Посмотрите вверху списка конструкторов:
https://en.cppreference.com/w/... shared_ptr
C++
1
std::share_ptr<Base>sptr(new Derived1(/*args*/));
как вариант. То есть new Derived1(/*args*/) прямо в emplace_back можно скормить.
1
 Аватар для Nishen
1358 / 856 / 366
Регистрация: 26.02.2015
Сообщений: 3,814
04.08.2020, 12:46  [ТС]
Спасибо, я понял!
0
 Аватар для Nishen
1358 / 856 / 366
Регистрация: 26.02.2015
Сообщений: 3,814
05.08.2020, 13:20  [ТС]
Вот конечный вариант, написанный на умных указателях:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include <array>
#include <iostream>
#include <memory>
#include <vector>
 
enum class Direction {
 
    north = 0, east, south, west
 
};
 
class MapSite {
 
public:
    virtual ~MapSite() { }
    virtual void enter() = 0;
 
};
 
class Room : public MapSite {
 
public:
    Room(int roomNumber) :
        sides_(), roomNumber_(roomNumber) { }
 
    ~Room() {
 
        std::cout << "The room with number " <<
            roomNumber_ << " was deleted\n";
 
    }
 
    auto getSide(Direction direction) const {
 
        return sides_[static_cast<int>(direction)];
 
    }
 
    void setSide(Direction direction, std::shared_ptr<MapSite> side) {
 
        sides_[static_cast<int>(direction)] = side;
 
    }
 
    int getRoomNumber() const {
 
        return roomNumber_;
 
    }
 
    virtual void enter() override { }
 
private:
    std::array<std::shared_ptr<MapSite>, 4> sides_;
    int roomNumber_;
 
};
 
class Wall : public MapSite {
 
public:
    Wall() { }
 
    ~Wall() {
 
        std::cout << "The wall was deleted\n";
 
    }
 
    virtual void enter() override { }
 
};
 
class Door : public MapSite {
 
public:
    Door(std::shared_ptr<Room> from, std::shared_ptr<Room> to) :
        from_(from), to_(to), isOpen_(false) { }
 
    ~Door() {
 
        std::cout << "The door was deleted\n";
 
    }
 
    virtual void enter() override { }
 
    auto otherSideFrom(std::shared_ptr<Room> room) {
 
        if (room == from_.lock())
            return to_.lock();
 
        if (room == to_.lock())
            return from_.lock();
 
        return std::shared_ptr<Room>();
 
    }
 
private:
    std::weak_ptr<Room> from_;
    std::weak_ptr<Room> to_;
    bool isOpen_;
 
};
 
class Maze {
 
public:
    Maze() { }
 
    ~Maze() { 
    
        std::cout << "The maze was deleted\n";
    
    }
 
    void addRoom(std::shared_ptr<Room> room) {
 
        rooms_.push_back(room);
 
    }
 
    auto getRoomByNumber(int roomNumber) const {
 
        for (const auto& room : rooms_) {
 
            if (room->getRoomNumber() == roomNumber)
                return room;
 
        }
 
        return std::shared_ptr<Room>();
 
    }
 
private:
    std::vector<std::shared_ptr<Room>> rooms_;
 
};
 
class MazeGame {
 
public:
    std::unique_ptr<Maze> createMaze() {
 
        maze_ = std::make_unique<Maze>();
        auto r1 = std::make_shared<Room>(1);
        auto r2 = std::make_shared<Room>(2);
        auto door = std::make_shared<Door>(r1, r2);
 
        maze_->addRoom(r1);
        maze_->addRoom(r2);
 
        r1->setSide(Direction::north, std::make_shared<Wall>());
        r1->setSide(Direction::east, door);
        r1->setSide(Direction::south, std::make_shared<Wall>());
        r1->setSide(Direction::west, std::make_shared<Wall>());
 
        r2->setSide(Direction::north, std::make_shared<Wall>());
        r2->setSide(Direction::east, std::make_shared<Wall>());
        r2->setSide(Direction::south, std::make_shared<Wall>());
        r2->setSide(Direction::west, door);
 
        return std::move(maze_);
 
    }
 
private:
    std::unique_ptr<Maze> maze_;
 
};
 
int main() {
 
    MazeGame game;
 
    game.createMaze();
 
    return 0;
 
}
0
19495 / 10100 / 2461
Регистрация: 30.01.2014
Сообщений: 17,808
05.08.2020, 13:25
Цитата Сообщение от Nishen Посмотреть сообщение
std::unique_ptr<Maze> maze_;
А зачем он член класса, если всегда move-ится?
0
 Аватар для Nishen
1358 / 856 / 366
Регистрация: 26.02.2015
Сообщений: 3,814
05.08.2020, 13:28  [ТС]
Это я эксперементировал и забыл убрать.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
05.08.2020, 13:40
может так

C++
1
2
private:
    std::vector<std::shared_ptr<MapSite>> rooms_;
?
C++
1
2
3
4
5
void addRoom( shared_ptr<MapSite> mapSite) {
 
        rooms_.emplace_back(mapSite);
 
    }
?
а потом
C++
1
2
3
4
5
6
7
8
9
10
11
12
 std::unique_ptr<Maze> createMaze() {
 
 
        maze_ = std::make_unique<Maze>();
 
        shared_ptr<MapSite> r1(new Room(1)),
         r2 (new Room>(2)),
         door (new Door(r1, r2));
 
        maze_->addRoom(r1);
        maze_->addRoom(r2);
//итп
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
05.08.2020, 13:51
del
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
05.08.2020, 15:28
Цитата Сообщение от zayats80888
Однако из соседних комнат в нее все еще можно попасть
zayats80888, я говорил о "ромашке" - узеле N-дерева. Каждый цветок имеет контейнер лепестков. И если разрешить им создавать (активизировать/передавать фокус) только друг от друга (кроме стартового), то они сами при передаче фокуса будут решать кого оставить и кого удалить из окружения. Тогда алгоритм владения чуть похитрее чем у просто умного указателя. Это паттерн "хитрый ромашка". Автоматический N-монстряжка.
А в принципе и на смартах это сделать можно. Создавать только фабрикой, (набирать контейнер лепестков). При активации лепестка - сам становится лепестком и мувает лепестки (пересекающийся набор) активизированному - будущему цветку. При уничтожении (когда лепесток не нужен) у него уже пустой контейнер и он не может грохнуть ни чего.
Можно для скорости даже 2-хуровневые ромашки реализовать (лепестки с лепестками). Это расточительнее но не потребует вычислений в жестких временных рамках. Там уже будут общие и это чуть сложнее.
Но всё, это уже легче самому написать, чем рассказать. Есть элемент получения части решения в процессе.
0
 Аватар для Nishen
1358 / 856 / 366
Регистрация: 26.02.2015
Сообщений: 3,814
05.08.2020, 18:57  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
может так
А зачем так делать? У нас же Maze по логике хранит уже целые комнаты?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
05.08.2020, 18:57
Помогаю со студенческими работами здесь

Паттерны проектирования, нужен код на С++ и UML диаграмма
Декоратор (Decorator) или Оболочка (Wrapper) - GoF Итератор (Iterator) или Курсор (Cursor) - GoF Одиночка (Singleton) - GoF

Объектно-ориентированного проектирования и проектирования на основе структур данных
Помогите решить задание, так как вообще не понимаю, что тут можно сделать. Решить задание с помощью объектно-ориентированного...

Паттерны
Паттерн Flyweight Паттерн Domain Model (Модель области определения).Кто знает что это.И может на сайте есть коды хоть примерно этого.

Паттерны
Пролистал всю главную страницу и решил поставить вопрос в С++ , чем сможите помогите. Суть , изучаю объектно ориентированное...

Порождающие паттерны
enum Direction {North, South, East, West} class MapSite { public: virtual void Enter() = 0; } class Room: public MapSite { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG-файла с альфа-каналом с помощью библиотеки SDL3_image на Android
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru