2011-03-03 19 views
9

Me encuentro frente a una situación en la que tengo un std::vector de boost::shared_ptr s de una clase base. Durante el curso de mi programa, necesito almacenar punteros compartidos a objetos de clase derivados en ese vector también y en algún momento más adelante en el programa, necesito recuperar esos punteros compartidos.boost :: shared_ptr and Herencia

siguiente código ilustra mi problema:

#include <iostream> 
#include <vector> 
using namespace std; 

#include <boost/make_shared.hpp> 
#include <boost/foreach.hpp> 

class Base 
{ 
public: 
    virtual ~Base() 
    { 
    } 
}; 
/******************************************/ 

typedef boost::shared_ptr<Base> BasePtr; 
/******************************************/ 

class Derived1 : public Base 
{ 
public: 
    void derived1_test() 
    { 
     cout << "derived1_test" << endl; 
    } 
    /******************************************/ 
    int i1; 
}; 
/******************************************/ 

typedef boost::shared_ptr<Derived1> Derived1Ptr; 
/******************************************/ 

class Derived2 : public Base 
{ 
public: 
    void derived2_test() 
    { 
     cout << "derived2_test" << endl; 
    } 
    /******************************************/ 
    int i2; 
}; 
/******************************************/ 

typedef boost::shared_ptr<Derived2> Derived2Ptr; 
/******************************************/ 

int main() 
{ 
    Derived1Ptr d1 = boost::make_shared<Derived1>(); 
    Derived2Ptr d2 = boost::make_shared<Derived2>(); 

    vector<BasePtr> v; 
    v.push_back(d1); 
    v.push_back(d2); 
    BOOST_FOREACH(BasePtr bPtr, v) 
    { 
     try 
     { 
      Derived1& d11 = dynamic_cast< Derived1& >(*bPtr); 
      d11.derived1_test(); 
     } 
     catch (const std::bad_cast& e) 
     { 
      Derived2& d22 = dynamic_cast< Derived2& >(*bPtr); 
      d22.derived2_test(); 
     } 
    } 
    return 0; 
} 

En el código anterior, si cambio el código en BOOST_FOREACH de

Derived1& d11 = dynamic_cast< Derived1& >(*bPtr); 

a

Derived1Ptr d11 = dynamic_cast<Derived1Ptr>(bPtr); 

, consigo siguiente compilación error de tiempo en VS2010

invalid target type for dynamic_cast target type must be a pointer or reference to a defined class 

Mi problema es que quiero trabajar con boost::shared_ptr sin referencias. En segundo lugar, estoy usando dynamic_cast que lanzará una excepción std::bad_cast cuando la referencia del objeto sea de un tipo diferente (intenté usarlo con punteros compartidos pero obtengo el error del compilador mencionado anteriormente). Eso es claramente muy lento. Quiero poder utilizar un enfoque más orientado al rendimiento. Lo que estoy buscando aquí es cualquier solución en lugar de usar dynamic_cast y manejo de excepciones.

Cualquier sugerencia con respecto al código o cambio en el diseño son bienvenidos.

+0

Si solo hay una clase derivada o si está seguro de su tipo, puede simplemente usar 'static_cast' para downcast. – JohnPS

+0

En realidad esta es una versión mucho más simple. En el código real hay 3 clases derivadas diferentes. –

+0

Y me di cuenta de que está utilizando 'shared_ptr' no punteros simples, por lo tanto haga caso omiso de mi consejo. – JohnPS

Respuesta

2

Si los vectores son dueños de los objetos, que sería mejor usar un boost::ptr_vector.

7

Parece que su diseño no tiene sentido; sería mejor usar las funciones virtual para lograr un comportamiento polimórfico.

#include <iostream> 
#include <vector> 
using namespace std; 

#include <boost/make_shared.hpp> 
#include <boost/foreach.hpp> 

class Base 
{ 
public: 
    virtual ~Base() {} 
    virtual void test() = 0; 
}; 
/******************************************/ 

typedef boost::shared_ptr<Base> BasePtr; 
/******************************************/ 

class Derived1 : public Base 
{ 
public: 
    void test() 
    { 
     cout << "derived1_test" << endl; 
    } 
    /******************************************/ 
    int i1; 
}; 

class Derived2 : public Base 
{ 
public: 
    void test() 
    { 
     cout << "derived2_test" << endl; 
    } 
    /******************************************/ 
    int i2; 
}; 

int main() 
{ 
    BasePtr d1 = boost::make_shared<Derived1>(); 
    BasePtr d2 = boost::make_shared<Derived2>(); 

    vector<BasePtr> v; 
    v.push_back(d1); 
    v.push_back(d2); 
    BOOST_FOREACH(BasePtr &bPtr, v) // I use a reference here for efficiency. 
    { 
     bPtr->test(); 
    } 
    return 0; 
} 
1

tiene varias opciones:

Uso herencia (polimorfismo) y correctamente! es decir, definir métodos virtuales puros en su clase base que implemente en su clase derivada (también, el tipo extra shared_ptr para cada tipo derivado es redundante)

Use un tipo de variante para contener todos los tipos derivados (útil si tiene conjunto limitado). No hay necesidad de lanzar dinámico, puede especificar que un visitante haga lo que necesita.

Cuestiones relacionadas