2010-10-13 13 views
5

Sto usando C++. C++ 0x che utilizza Visual Studio 2010 per essere corretto.Come si comportano i puntatori intelligenti non intrusivi rispetto all'ereditarietà e all'ereditarietà multipla?

Supponiamo di avere una classe Z. Per rendere più sicuro nella mia applicazione lavorare con i puntatori a questa classe, posso usare costantemente puntatori intelligenti (puntatore condiviso, puntatore debole).

Ora questa classe Z eredita da una classe X. Alcune parti del mio applicazione funziona con i puntatori a classe X, gli altri lavoreranno con puntatori a classe Z.

  • È ancora possibile utilizzare puntatori intelligenti?
  • I puntatori condivisi funzionano ancora se ne ho alcuni che fanno riferimento a X e altri che si riferiscono a Z? È garantito che la distruzione dell'ultimo puntatore condiviso all'istanza (indipendentemente dal fatto che sia std::shared_ptr<X> o std::shared_ptr<Z>) cancella l'istanza? Sono sicuro che se elimino std::shared_ptr<X>, l'istanza viene mantenuta finché c'è un altro std::shared_ptr<Y>?

Ora supponiamo che io uso l'ereditarietà multipla, dove Z eredita dalle classi X e Y. Alcune parti del mio applicazione funziona con std::shared_ptr<X>, altri con std::shared_ptr<Y> e altri con std::shared_ptr<Z>.

  • Posso ancora utilizzare i puntatori condivisi in questo modo?
  • È ancora garantito che solo l'ultimo puntatore intelligente (indipendentemente dal fatto che punti a X, Y o Z) cancelli l'istanza?

A proposito, come posso trasmettere in modo sicuro un puntatore intelligente a un altro, ad es. cast std::shared_ptr<Z> a std::shared_ptr<X>? funziona? È permesso?

Si noti che faccio esplicitamente riferimento a puntatori non intrusivi (come il nuovo std::shared_ptr e std::weak_ptr in C++ 0x). Quando si utilizzano puntatori intrusivi (come in Boost), probabilmente funziona poiché l'istanza stessa è responsabile della gestione del contatore.

risposta

6

Sì, questo è supportato dallo standard, §20.9.11.2.10 [util.smartptr.shared.cast].

I utils necessari sono:

  • std::static_pointer_cast<>()
  • std::dynamic_pointer_cast<>()

hanno la stessa semantica loro C++ 03 contatore parti static_cast<>() e dynamic_cast<>(). L'unica differenza è che funzionano solo su std::shared_ptr s. E solo a verbose, fanno quello che ti aspetti e condividono correttamente il conteggio dei riferimenti tra il cast originale e quello appena lanciato shared_ptr.

struct X { virtual ~X(){} }; 
struct Y : public X {}; 
struct Z : public X {}; 

int main() 
{ 
    { 
     //C++03 
     X* x = new Z; 
     Z* z = dynamic_cast<Z*>(x); 
     assert(z); 
     x = new Y; 
     z = dynamic_cast<Z*>(x); 
     assert(!z); 
     z = static_cast<Z*>(x); 
     assert(z); //EVIL!!! 
    } 

    { 
     //C++0x 
     std::shared_ptr<X> x{new Z}; 
     std::shared_ptr<Z> z{std::dynamic_pointer_cast<Z>(x)}; 
     assert(z); 
     x = std::make_shared<Y>(); 
     z = std::dynamic_pointer_cast<Z>(x); 
     assert(!z); 
     z = std::static_pointer_cast<Z>(x); 
     assert(z); //EVIL!!! 

     // reference counts work as expected. 
     std::shared_ptr<Y> y{std::static_pointer_cast<Y>(x)}; 
     assert(y); 

     std::weak_ptr<Y> w{y}; 
     assert(w.expired()); 

     y.reset(); 
     assert(w.expired()); 

     x.reset(); 
     assert(!w.expired());  
    } 
    { 
     //s'more nice shared_ptr features 
     auto z = std::make_shared<X>(); 
     std::shared_ptr<X> x{z}; 
     assert(z == x); 
     x = z; //assignment also works. 
    } 
} 
+0

Wow mai sentito parlare di questo ... O__O Nessun riferimento a questo in qualsiasi risorsa sono riuscito a trovare il C++ 0x diverso da quello (indigest) progetto ... – Klaim

+0

Non sapevo per certo i calchi dove sono finchè non l'ho guardato. Ho tuttavia fortemente sospettato che fossero lì perché facevano parte della libreria Boost.Smartptr originale. –

+0

Si prega di liberarsi di "std ::" davanti agli operatori di cast integrati.Inoltre, un cast dinamico di questo tipo richiede classi polimorfiche. Le tue classi di esempio non sono polimorfiche. – sellibitze

Problemi correlati