Domanda

Ho una classe con un puntatore (non intelligente) a un oggetto interfaccia (chiamiamolo pInterface) e sto costruendo una classe nidificata che ha anche bisogno di accedere a quell'interfaccia. Ho intenzione di aggirare questo passaggio passando il puntatore all'interfaccia nel costruttore della classe nidificata in questo modo:

CNestedClass someClass( pInterface, ... );

Tuttavia non sono sicuro del modo migliore di memorizzare questo puntatore nella classe nidificata. Potrei usare:

1) A scoped (or other smart) pointer (to the original object)
2) A pointer to a pointer 

Cosa suggerireste ragazzi e perché?

EDIT: dovrei chiarire - la classe nidificata dovrà chiamare metodi sull'oggetto interfaccia, tuttavia non lo crea (o modifica l'oggetto 'puntato'), la classe padre ne è responsabile.

È stato utile?

Soluzione

L'uso di un puntatore a un puntatore è se una delle due classi può modificare il valore del puntatore, ad es. eliminando l'oggetto esistente e sostituendolo con uno nuovo. Ciò consente ad entrambe le classi di utilizzare ancora lo stesso oggetto dereferenziando il puntatore al puntatore.

In caso contrario, la preoccupazione è garantire che l'oggetto rimanga valido per tutta la durata di entrambe le classi.

  • Se la classe nidificata dura meno, non devi preoccuparti.
  • Se è lo stesso, purché tu pulisca nell'ordine corretto (ad es. prima la classe nidificata, poi l'oggetto), non devi preoccuparti
  • Se la classe nidificata potrebbe persistere dopo la distruzione del proprietario, è necessario implementare un modo per garantire che anche l'oggetto persista.

Se è necessario garantire la durata dell'oggetto, è possibile farlo tramite la semantica di conteggio dei riferimenti, manualmente o tramite un'interfaccia con puntatore intelligente.

Per un puntatore intelligente, quindi boost :: shared_ptr sarebbe una buona scelta. shared_ptr consente di condividere la proprietà di un oggetto con più puntatori. Quando l'ultimo shared_ptr esce dall'ambito, l'oggetto viene eliminato.

(nota che non è il caso di auto_ptr, dove un oggetto è di proprietà esclusiva).

Cose di cui essere a conoscenza;

  1. Quando si utilizza boost :: shared_ptr, assicurarsi che la classe nidificata abbia una copia di shared_ptr e non un riferimento / puntatore.
  2. std :: auto_ptr si comporta in modo abbastanza diverso, gli oggetti sono di proprietà esclusiva e non condivisi
  3. boost :: shared_ptr può funzionare solo con oggetti heap, ad esempio i puntatori restituiti da una chiamata a "new"

Esempio:

typedef boost::shared_ptr<Interface> shared_interface;

class NestedClass
{
  shared_interface mInterface; // empty pointer
}

void NestedClass::setInterface(shared_interface& foo)
{
  mInterface= foo; // take a copy of foo.
}

void ParentClass::init( void )
{
  // mInterface is also declared as shared_interface
  mInterface = new Interface();
  mNestedClass->setInterface(mInterface);
}

Altri suggerimenti

L'altro motivo per cui potresti voler utilizzare un puntatore a un puntatore sarebbe se il codice esterno potrebbe cambiare il valore del puntatore originale (ad es. farlo puntare a un nuovo oggetto o impostarlo su NULL dopo aver rilasciato l'oggetto a cui punta). Tuttavia, IMO è una cattiva pratica cambiare un puntatore dopo averlo dato a qualcun altro.

Quindi, se né il codice esterno né la classe nidificata cambiano il puntatore, archiviarlo nella classe nidificata come copia del puntatore originale come variabile membro (campo).

Passa l'indirizzo di un puntatore alla tua interfaccia (IMyInterface ** ppInterface) e riempi il puntatore se è implementato dalla classe.

La classe può trasmettere questo puntatore a quell'interfaccia e compilare il puntatore * ppInterface. Se la classe non implementa questa interfaccia, può impostare * ppInterface su NULL.

Fondamentalmente, stai condividendo un puntatore allo stesso oggetto tra due oggetti diversi. Se non si utilizza alcun puntatore intelligente, è sufficiente archiviare il puntatore sull'oggetto condiviso. È necessario fare attenzione alla proprietà dell'oggetto condiviso, ovvero quale oggetto è responsabile di deallocare l'oggetto condiviso e notificare agli altri che non c'è più.

class Outer
{
    class Inner
    {
    };
};

Poiché un oggetto di Outer contiene solo un puntatore RAW su un oggetto pInterface, ciò implica che l'oggetto Outer non possiede o non ha alcun controllo sulla durata dell'oggetto pInterface. Speriamo quindi che ci sia una certa garanzia che l'oggetto pInterface vivrà finché l'oggetto esterno; In questo caso non vi è alcun motivo per usare un puntatore, si potrebbe semplicemente usare un riferimento (supponendo che non ci sia una situazione in cui pInterface sarebbe NULL).

Come dipende Inner come "riferimento" (non riferimento C ++) e in realtà abbiamo bisogno di maggiori informazioni sulla relazione tra gli oggetti coinvolti!

  • Qual è la realizzazione tra oggetti interni ed esterni.
  • Qual è la durata di un oggetto Interno in relazione all'oggetto Esterno da cui ha ereditato il puntatore pInterface?
  • Qual è la garanzia che un oggetto esterno abbia una durata inferiore a un oggetto pInterface.

ecc.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top