Наверху, я угадаю ... нет, его не существует (по крайней мере, не для C ++).
Ваше предложение подразумевает сложную ситуацию (даже если выне использовал обратные вызовы).Вы просите что-то, что, по своему собственному уничтожению, позаботится об удалении любой ссылки о себе (потенциально) из любой структуры данных, которая ссылается на нее.Это довольно сложный заказ, и он не предназначен для STL.
Если вы действительно хотите это сделать (и я уверен, что вы это делаете), то вот мои первые мысли.Каждый раз, когда ваш объект добавляется в структуру данных, вы можете потребовать, чтобы структура данных была зарегистрирована в объекте, например, с помощью метода, подобного Object::Register(const std::vector<Object> &v)
.Затем вы можете сохранить ссылку (фактически, вы, вероятно, захватите указатель) на vector
, так что вы можете сказать vector
, чтобы удалить объект при уничтожении.Конечно, у этого есть две проблемы:
- Это все еще сумасшедший комплекс (особенно если вы хотите поддерживать больше структур, чем только векторы, и даже больше, если вы ищете полностью общее решение).
- Требуется, чтобы другой кодер следовал этому стилю везде, где объект добавляется в структуру
- Возможно, потребуется редактировать деструктор
Object
, который вы явно нам сказали, что это не должно делать.
Так что, да, там особой помощи нет.
Лично у меня есть гораздо более предпочтительное решение, которое вращается вокруг событий (в частности, событие на основе делегата, например,что мы используем в c #).Если вы не знакомы с тем, как это работает, вы можете прочитать это руководство по программированию .С другой стороны, вы можете этого не делать, поскольку мы используем c ++, а не c #, и, поскольку я в значительной степени опишу это сам.
Одна из причин, по которой мне нравится идея события, заключается в том, что вы уже используете обратные вызовы.Делегаты (как в c # делегатах) являются просто расширением обратных вызовов.Они в основном инкапсулируют поведение vector<Callback>
в классе Delegate
.Класс Delegate
позволяет вызывать все эти методы одной операцией, если вы перегружаете оператор вызова функции.Также, как и delegate
, который вы уже используете, он, скорее всего, будет параметризованным типом.(На самом деле, когда C++0x
все готово к работе, что скоро произойдет, вариационных шаблонов также будет весьма полезным).
Anyhoo, смысл всего этогов том, что вы могли бы иметь такую Delegate
переменную-член любого из ваших классов:
class Object
{
public:
... // whatever constructors, etc. you might need
Delegate<void, Collection, EventArgs> destroyHandler;
... // and number of event handlers can be used.
};
Теперь любой класс структуры данных может зарегистрировать обратный вызов, например:
obj.destroyHandler += myDelegate;
, где myDelegate
- любая функция с необходимым типом.
Однако этот подход имеет больше проблем.В частности, требуется целая новая библиотека, заполненная структурами данных, которые осведомлены о вашей модели событий.Это не должно быть действительно сложно, так как существующие контейнеры STL могут быть просто упакованы.Это было бы просто много работы, и каждый должен был бы решить использовать вашу новую библиотеку.
Еще одна ошибка найдена в строке Delegate<void, Collection, EventArgs> destroyHandler;
.Что означает каждый из этих параметров типа?Ну, void
должно быть довольно ясно: это просто тип возврата методов.Кроме того, EventArgs
просты: он просто переносит все данные, которые необходимо передать обратным вызовам.Тип Collection
самый странный - зачем нам параметризировать используемую коллекцию типов?
Это обходить неловкость использования функций указателя на член в c ++.Хотя такие указатели возможны, их ужасно использовать, и (насколько мне известно) нет способа взять функции указателя на член из нескольких типов и сохранить их в одной коллекции.
Вместо этого, то, что я пробовал в прошлом (хотя я на самом деле не закончил идею), было что-то вроде
class MyVector
{
static void DestructionHandler( MyVector & v, EventArgs & args )
{
// ... Handler code goes here
}
};
Обратите внимание на параметр MyVector & v
: он заменяет обычный this
указательТакже обратите внимание, что метод static
- это позволяет использовать его в качестве обычного старого указателя на функцию в стиле C.
В любом случае, я бы немного увлекся, но, собрав все это вместе, вы можете получить довольно приличную систему, основанную на событиях, которая довольно популярна в других языках ООП.Кроме того, я сказал вам, что это был высокий заказ!