Справочная информация: В одном из моих проектов у меня есть абстрактный класс со статическим интерфейсом для отслеживания использования ресурсов другими объектами.Класс Track выглядит следующим образом:
https://github.com/mkoskim/games/blob/master/engine/util/track.d
Как видите, другие классы / объекты вызывают функции добавления и удаления.Класс отслеживания принимает объект в качестве аргумента и использует информацию, извлеченную из объекта, для отслеживания использования: текущая реализация создает таблицу поиска, содержащую счетчики ссылок из имени класса.Вывод отслеживания выглядит примерно так:
![Tracked objects](https://i.stack.imgur.com/k67DM.png)
D имеет автоматическое управление памятью, поэтому нет смысла отслеживать это.Но эти определенные объекты содержат внешние ресурсы - в данном случае, такие вещи, как текстуры, буферы вершин и т. Д., И мне нравится видеть, что они освобождаются в правильных ситуациях, то есть, например, переключение на новый уровень в игре работает правильно,и нет никаких свободных ссылок на объекты на предыдущем уровне.
Проблема: Теперь, хотя это работает, на мой взгляд, это немного комковатый механизм.Мне нужно добавить вызовы конструктора класса и деструктора, чтобы отслеживать его.Во многих случаях мои классы имеют много разных конструкторов, и мне нужно убедиться, что Track :: add () вызывается один раз и только один раз на этапе построения.Например,
https://github.com/mkoskim/games/blob/master/engine/gpu/shader.d#L326
... здесь вы можете увидеть, начиная со строки 334, один пример конструктора "конструкция".Это работает, но всякий раз, когда касаются конструкторов и их дерева вызовов, мне нужно быть осторожным с отслеживанием.
Вопрос: Я почти уверен, что у D есть несколько мощных инструментов дляавтоматизировать такие вещи.В основном я искал механику, аналогичную scope (), для внедрения вызовов функций в время жизни объекта (создание и удаление).
Конечно, есть и другие возможные решения.Один из способов, знакомый по C ++, конечно, будет наследовать отслеживаемые объекты из класса Track (ed), например
class Shader : Tracked { ... }
Но я бы не хотел использовать это сам, так как это приведет к проблемам, если классв любом случае является производным от некоторого другого класса.Я, конечно, открыт для предложений, заставляющих эту работу как-то работать, например,
class Shader : BaseShader, Tracked { ... }
Другой способ может создать составные классы, чтобы объект трекера был построен и разрушен в соответствии с его родителем?Что-то вроде:
class Shader {
...
private Tracked tracked = new Tracked(self);
...
this() { ... }
this(int) { ... }
this(string) { ... }
...
~this() { ... }
}
Лично я чувствую себя немного странно, что мне нужно прикрепить дополнительные ненужные блоки памяти в виде объекта Tracked к другим объектам (так как мне нужно только ввести вызовы конструктора родительского класса идеструктор).
Какие еще есть способы?
Если это смущает, не стесняйтесь попросить меня прояснить вопрос.