Domanda

Questo è un po 'un problema coinvolto, quindi farò del mio meglio per spiegare cosa sta succedendo. Se mi manca qualcosa, la prego di dirmi in modo da poter chiarire.

abbiamo un sistema di richiamata in cui da una parte di un modulo o di applicazione fornisce un "servizio" ed i clienti possono eseguire azioni con questo servizio (A molto rudimentale IPC, in fondo). Per riferimento futuro Diciamo che abbiamo alcune definizioni in questo modo:

typedef int (*callback)(void*); // This is NOT in our code, but makes explaining easier.

installCallback(string serviceName, callback cb); // Really handled by a proper management system

sendMessage(string serviceName, void* arg); // arg = value to pass to callback

Questo funziona bene per i tipi di base, come le strutture o comandi incorporati.

Abbiamo una struttura MI un po 'come questo:

Device <- Disk <- MyDiskProvider

class Disk : public virtual Device
class MyDiskProvider : public Disk

Il fornitore può essere qualsiasi cosa, da un driver hardware per un po 'di colla che le immagini maniglie disco. Il punto è che le classi ereditano disco.

Abbiamo un "servizio", che deve essere notificata di tutti i nuovi dischi nel sistema, e questo è dove le cose si dipanano:

void diskHandler(void *p)
{
    Disk *pDisk = reinterpret_cast<Disk*>(p); // Uh oh!

    // Remainder is not important
}

SomeDiskProvider::initialise()
{
    // Probe hardware, whatever...

    // Tell the disk system we're here!
    sendMessage("disk-handler", reinterpret_cast<void*>(this)); // Uh oh!
}

Il problema è, SomeDiskProvider eredita disco, ma il gestore di callback non può ricevere quel tipo (come il puntatore a funzione di callback deve essere generico).

Potrebbe RTTI e modelli di aiutare qui?

Qualche suggerimento sarebbe molto apprezzato.

È stato utile?

Soluzione

Mentre io non sono sicuro al 100% credo static_cast da T * a * e di nuovo all'originale tipo di puntatore T * dovrebbe funzionare vuoto. A mio avviso il problema è che reinterpret_cast cambia solo il tipo di puntatore senza alterarne il valore reale e static_cast in caso di successione dovrebbe regolare un puntatore in modo che punti all'inizio dell'oggetto.

NOTA BENE:. Sei sul lato oscuro del linguaggio qui e non posso garantire che funzionerà a tutti

Altri suggerimenti

Il codice è rischioso. Il problema è che lanci una SomeDiskProvider * per void * e poi lanci di nuovo a Disk *.

Si dovrebbe lanciare di nuovo al tipo esatto lanci da. Così si potrebbe prima lanciare la vostra SomeDiskProvider * ad un Disk *:

reinterpret_cast<void*>(static_cast<Disk *>(this))

o che lanci di nuovo ad un SomeDiskProvider *:

SomeDiskProvider *pDisk = reinterpret_cast<SomeDiskProvider*>(p);

reinterpret_cast<> è OK se si sta convertendo da some_type * a void * e viceversa. Tuttavia, lei ha detto che si sta utilizzando l'ereditarietà multipla, in cui this caso in una classe nella gerarchia non può avere lo stesso valore di this in un'altra classe; dynamic_cast<> è stato studiato per l'albero di ereditarietà e vi darà la risposta giusta.

Quindi, in uso SomeDiskProvider entrambi i calchi:

SomeDiskProvider::initialise()
{
    // Gets the right value for 'this' for the Disk part of SomeDiskProvider.
    Disk *pDisk = dynamic_cast<Disk *>(this);

    // OK, since the callback converts it back to Disk *
    sendMessage("disk-handler", reinterpret_cast<void*>(this));
}

Il callback è esattamente come si mostrò nella sua interrogazione.

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