Считать любую ссылку на класс с помощью наследования?

В моем новом проекте я хочу (в основном, чтобы увидеть, как это будет работать) полностью запретить необработанные указатели в моем коде.

Мой первый подход заключался в том, чтобы позволить всем классам унаследовать от этого простого класса: шаблон class Base {public: typedef std :: shared_ptr ptr; };

И просто используйте class :: ptr везде, где мне нужен указатель.

Этот подход казался подходящим, пока я не понял, что иногда мои объекты хотят передавать указатель this на другие объекты. Разрешить моим объектам просто обернуть его в shared_ptr не получится, поскольку тогда у одного и того же указателя может быть два владельца. Я полагаю, это плохо.

Моя следующая идея состояла в том, чтобы изменить класс «Базовый», чтобы реализовать сам подсчет ссылок, таким образом, каждый экземпляр классов, наследуемых от «Базового», может иметь только один счетчик.

Это хорошее решение, есть ли что-нибудь лучше и может ли Boost и / или stl уже решить эту проблему для меня?


person monoceres    schedule 01.07.2010    source источник
comment
Почему вы хотите полностью запретить необработанные указатели? Вы пытаетесь избежать принятия проектных решений о праве собственности на объект?   -  person CB Bailey    schedule 01.07.2010
comment
В некоторых случаях да, мой проект - это игра, в которой объекты могут не иметь четкого владельца (то есть враг порождает другого врага, а затем умирает. Но это также большой эксперимент, насколько далеко вы можете зайти в эту концепцию. Кроме того, есть также лень о том, чтобы никогда не думать об управлении памятью!;)   -  person monoceres    schedule 01.07.2010
comment
@Charles Я на самом деле думаю, что это неплохая идея, если мы перефразируем это немного по-другому, имея очень строгое соответствие RAII. Однако я бы перефразировал это так: полностью запретить необработанные указатели для управления памятью. Было бы очень сложно полностью избежать передачи «сырых» указателей, но можно было бы с твердой политикой и запуском новой кодовой базы построить все, используя только scoped_ptr и scoped_array. Они уже формируют RAII-совместимые примитивы для хранения результатов оператора new / new [] вместо «сырых» указателей.   -  person stinky472    schedule 01.07.2010
comment
@Charles ... или, возможно, лучше сказать, полностью запретить любые случаи, когда требуются явные вызовы delete / delete [], даже при реализации класса. Мы по-прежнему можем эффективно делать что угодно с scoped_ptr и scoped_array в качестве наших примитивов управления памятью. указателей. Единственный случай, когда явное освобождение памяти неизбежно, - это если кто-то желает реализовать распределитель памяти или реализовать структуру данных, которая его использует.   -  person stinky472    schedule 01.07.2010
comment
@ stinky472: Я думаю, что это хорошая политика, чтобы никогда не использовать вручную delete или delete[], но вопрос не об этом. Безусловно, выбор, когда и где получить долевую собственность, является необходимой частью процесса проектирования; запрет на любое использование необработанных указателей не является ни заменой этого, ни практичным во многих проектах.   -  person CB Bailey    schedule 01.07.2010
comment
Только один счетчик ссылок? Ну, это зависит от того, есть ли у вас алмазное наследование, тогда у вас может быть несколько экземпляров Base в объекте и, следовательно, несколько разных счетчиков.   -  person Matthieu M.    schedule 01.07.2010
comment
@ Чарльз согласился. Также я думаю, что OP должен знать, что равномерное применение подсчета ссылок имеет свою долю головных болей (циклические ссылки, время жизни объектов продлевается намного дольше, чем следовало бы, только потому, что некоторый класс A хранит сильную ссылку на B и т. Д.). К сожалению, я работаю в такой системе, и хотя подсчет ссылок полезен для работы с общими ресурсами в потоках, делать это для всего - это настоящая PITA.   -  person stinky472    schedule 01.07.2010
comment
@Matthieu: Думаю, я сформулировал это неправильно. Я имел в виду, что если бы у одного объекта было два владельца, то к объекту применялись бы два разных счетчика ссылок. @ stinky472: Вы, наверное, правы, и, как я уже сказал, это скорее тест, чтобы увидеть, как далеко вы можете зайти. Поскольку api, с которым я работаю, находится на C, мне уже приходилось делать исключения.   -  person monoceres    schedule 01.07.2010
comment
@monoceres, если вы продолжите использовать этот подход, будьте осторожны при хранении устойчивых сильных ссылок. Отдавайте предпочтение слабым ссылкам (weak_ptr), когда вы можете использовать постоянное хранилище для чего угодно, кроме одного «владельца», если только несколько действительно не необходимы, и вы избежите многих головных болей.   -  person stinky472    schedule 01.07.2010


Ответы (1)


Вы можете взглянуть на enable_shared_from_this.

С другой стороны, при использовании shared_ptr необходимо помнить о возможности циклических ссылок. Чтобы избежать этого, вы можете использовать weak_ptr. Это означает, что вам понадобится способ различать их, поэтому простого определения typedef class::ptr может быть недостаточно.

person Björn Pollex    schedule 01.07.2010
comment
Как раз то, что я хотел! Я почувствовал подъем, уже получил ответ. Я предполагаю, что другой typedef для weak_ptr решит эту проблему. - person monoceres; 01.07.2010