Uso de enable_shared_from_this con herencia múltiple

3 minutos de lectura

Avatar de usuario de Aarkan
Aarkan

BI estoy usando enable_shared_from_this en mi código, y no estoy seguro si su uso es correcto. Este es el código:

class A: public std::enable_shared_from_this<A>
{
public:
    void foo1()
    {
        auto ptr = shared_from_this(); 
    }
};

class B:public std::enable_shared_from_this<B>
{
public:
    void foo2()
    {
        auto ptr = shared_from_this(); 
    }
};

class C:public std::enable_shared_from_this<C>
{
public:
    void foo3()
    {
        auto ptr = shared_from_this(); 
    }
};

class D: public A, public B, public C
{
public:
    void foo()
    {
        auto ptr = A::shared_from_this(); 
    }
};

¿Son estos usos de make_shared_from_this() correcto, asumiendo que siempre están siendo llamados a través shared_ptr de D?

  • no creo foo2 o foo3 compilaria…

    – Aschepler

    18 de abril de 2013 a las 12:23

  • sí, eso no tiene sentido, solo la clase A hereda enable_shared_from_this

    – Stéphane Rolland

    18 de abril de 2013 a las 12:40

  • Creo que deberías echar un vistazo a lo que hace enable_shared_from_this. Ver la respuesta a esta pregunta

    – indeterminadamente secuenciado

    18 de abril de 2013 a las 12:43

  • posible duplicado de stackoverflow.com/questions/14939190/…

    –Andriy Tylychko

    18 de abril de 2013 a las 12:46

  • si que es mejor 🙂

    – Stéphane Rolland

    18 de abril de 2013 a las 12:53

Avatar de usuario de Offirmo
Ofirmo

Efectivamente lo estás haciendo mal. Si tiene herencia simple, simplemente herede de enable_shared_from this en la clase base, y la clase derivada lo obtienen gratis. (por supuesto, tendrás que rebajar el resultado)

Si tiene herencia múltiple (como parece), debe usar el truco descrito aquí y también aquí:

/* Trick to allow multiple inheritance of objects
 * inheriting shared_from_this.
 * cf. https://stackoverflow.com/a/12793989/587407
 */

/* First a common base class
 * of course, one should always virtually inherit from it.
 */
class MultipleInheritableEnableSharedFromThis
: public std::enable_shared_from_this<MultipleInheritableEnableSharedFromThis> {
public:
  virtual ~MultipleInheritableEnableSharedFromThis()
  {}
};

template <class T>
class inheritable_enable_shared_from_this
: virtual public MultipleInheritableEnableSharedFromThis {
public:
  std::shared_ptr<T> shared_from_this() {
    return std::dynamic_pointer_cast<T>(
        MultipleInheritableEnableSharedFromThis::shared_from_this()
    );
  }
  /* Utility method to easily downcast.
   * Useful when a child doesn't inherit directly from enable_shared_from_this
   * but wants to use the feature.
   */
  template <class Down>
  std::shared_ptr<Down> downcasted_shared_from_this() {
    return std::dynamic_pointer_cast<Down>(
       MultipleInheritableEnableSharedFromThis::shared_from_this()
    );
  }
};

Entonces tu código se convierte en:

class A: public inheritable_enable_shared_from_this<A>
{
public:
    void foo1()
    {
        auto ptr = shared_from_this(); 
    }
};

class B: public inheritable_enable_shared_from_this<B>
{
public:
    void foo2()
    {
        auto ptr = shared_from_this(); 
    }
};

class C: public inheritable_enable_shared_from_this<C>
{
public:
    void foo3()
    {
        auto ptr = shared_from_this(); 
    }
};

class D: public A, public B, public C
{
public:
    void foo()
    {
        auto ptr = A::downcasted_shared_from_this<D>(); 
    }
};

  • Nota: las clases derivadas solo podrán usar el enable_shared_from_this heredado si es público, es decir: class BaseClass: public enable_shared_from_this<BaseClass>.

    – Andrés

    30 de mayo de 2017 a las 3:14

  • @Offirmo ¿Hay alguna solución posible en caso de que no pueda modificar (heredar de legacy_enable_shared_from_this) las clases base (A, B, C)?

    –Ehtesham Hasan

    30 de abril de 2018 a las 4:04

¿Ha sido útil esta solución?