Подклассы и get_shared_from_this () - PullRequest
7 голосов
/ 19 марта 2012

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

class Parent : public enable_shared_from_this {
  ...
}

class Child : public Parent {
  public Child(){
    boost::shared_ptr<Parent> pointer=shared_from_this(); // should work
    boost::shared_ptr<Child> pointer=shared_from_this(); // won't work.

  ...
}

Как получить правильный интеллектуальный указатель с помощью shared_from_this ()?

CONTEXT:

Я пишу немного материала для уведомителя / слушателя, и некоторые классы, естественно, должны будут регистрироваться и отменять регистрацию в уведомителе.Например,

class Body : extends Listener<BodyMessage>{ // listen for BodyMessage messages
  public:
    Body() {
      Notifier<BodyMessage>::register(this); // register with the appropriate notifier
    }

    virtual ~Body {
      Notifier<BodyMessage>::unregister(this); // unregister
    }

    bool notify(BodyMessage m){ ... }

  ...
}

Обычно я просто использовал бы указатель this , и все было бы хорошо.Я заставил Уведомитель использовать шаблоны, поэтому я могу передавать сообщения только тем, кто хочет их услышать.

Однако я хочу использовать умные указатели.Если уведомитель выглядит так:

template<typename t>
class Notifier {
  public:
    static void register<boost::shared_ptr<Listener<t>>> boost::shared_ptr<Listener<t>> listener);

  ...
}

, то я больше не могу использовать указатель this .Естественно, я сделал Body extension enable_shared_from_this:

class Body : public boost::enable_shared_from_this, public Listener<BodyMessage> {
  public:
    Notifier<BodyMessage>::register(get_shared_ptr());
  ...
}

И это, похоже, работает для тел.Это не работает, однако, для подклассов тел (или, по крайней мере, кажется, что это не так):

class BodyChild : public Body {
  public:
    BodyChild(){
      Notifier<BodyMessage>::register(get_shared_ptr());
}

вероятно, потому что я не могу разыграть shared_pointer,Итак, могу ли я найти решение, которое

  • позволяет мне использовать общие указатели для слушателей (так как эти слушатели также используются в других контекстах интеллектуальных указателей),
  • позволяет мне шаблонировать Notifierи слушатели, использующие сам тип сообщения для шаблона, так что очень легко слушать конкретные сообщения, и поэтому мне не нужно декодировать сообщение, а
  • просто?

Я открыт для других идей, но если я смогу заставить это работать, я буду в восторге.

1 Ответ

6 голосов
/ 19 марта 2012

Вы можете разыгрывать умные указатели, и Boost предоставляет вам несколько шаблонов для облегчения этого. Например, у вас есть static_pointer_cast и dynamic_pointer_cast, которые позволяют вам проводить "через" указатель.

Поскольку this имеет правильный динамический тип, вы можете вызвать boost::static_pointer_cast для возвращаемого значения shared_from_this():

boost::shared_ptr<Child> p = static_pointer_cast<Child>(shared_from_this());

(не нужно готовиться static_pointer_cast благодаря поиску Кенига)

...