2015-09-09 9 views
6

codice dalla libreria: segmento di codiceEliminazione oggetto chiamante in modo sicuro all'interno di una funzione di callback segmento

class Client{ 
public: 
    class CallBack { 
    public: 
     virtual void onData(Client* caller, std::string& data) =0; 
    }; 

    Client(CallBack* callback):m_callBack(callback){} 
    virtual ~Client(){} 
    void onData(std::string data) { 
     m_callBack->onData(this, data); 
     m_totalDataVol += data.size(); 
    } 

private: 
    CallBack* m_callBack; 
    int m_totalDataVol = 0; 
} 

dall'applicazione:

class AppHandler: public Client::Callback { 
    void onData(Client* caller, std::string& data) { 
     /* Some complex logic and check certain conditions*/ 
      delete caller; // Application will crash, due to 
          // accessing member of deleted object (m_totalDataVol) 
    } 
} 

Oltre oggetto chiamante (istanza della classe Client) è di proprietà di l'applicazione, e l'applicazione nessuna restrizione per eliminarlo.

Come si supera questo problema?

Molto complesso scenario: Client classe della libreria di base può essere prorogato di un un'altra libreria (ClientEx classe) e l'applicazione potrebbe utilizzare tale libreria estesa (non la libreria di base)

risposta

2

Avere il callback restituire un bool indicando se il chiamante deve cancellare se stesso. Non eliminare il client dalla richiamata.

Inoltre, il callback deve essere chiamato a tutti se data.size == 0? Il Client potrebbe verificare questa condizione prima di chiamare il callback ed eliminare se stesso (o altrimenti gestirlo in modo appropriato).

Se la richiamata ancora ha bisogno di essere chiamato, forse si può evitare di modificare il tipo di ritorno semplicemente controllando lo stato nel client dopo la chiamata:

void onData(std::string data) { 
    m_callBack->onData(this, data); 
    if (data.size() != 0) { 
     m_totalDataVol += data.size(); 
    } 
    else { 
     delete this; 
    } 
} 

In alternativa, se proprio deve consentire la richiamata per eliminare il client, quindi hai bisogno di un modo per rintracciare quando il client è stato cancellato, che è possibile utilizzare all'interno del client stesso. Questo significa mantenere un riferimento a un altro oggetto.

class Client{ 
public: 
    class CallBack { 
    public: 
     virtual void onData(Client* caller, std::string& data) =0; 
    }; 

    Client(CallBack* callback):m_callBack(callback){}, was_deleted(nullptr) 
    virtual ~Client(){ 
     if (was_deleted) *was_deleted = true; 
    } 
    void onData(std::string data) { 
     bool *was_deleted = new bool(); 
     this->was_deleted = was_deleted; 
     m_callBack->onData(this, data); 
     if (! *was_deleted) { 
      m_totalDataVol += data.size(); 
      this->was_deleted = nullptr; 
     } 
     delete was_deleted; 
    } 

private: 
    CallBack* m_callBack; 
    int m_totalDataVol = 0; 
    // When issuing a callback, holds a pointer to a flag that can 
    // be used to track if this object has been deleted: 
    bool * was_deleted; 
} 

(Si noti che la suddetta soluzione non è thread-safe, ma potrebbe probabilmente essere reso così noti inoltre il codice precedente non viene compilato, come il codice di esempio nella tua domanda no - ho cercato di abbinare il codice originale nel miglior modo possibile, il principio dovrebbe essere applicabile al codice reale).

+0

Lo sviluppatore di applicazioni dovrebbe esserne a conoscenza. Ma in questo caso non sono in grado di aggiungere allo sviluppatore dell'applicazione. Un'altra cosa è come applicare "non eliminare l'oggetto chiamante". E questo è solo un codice di esempio, ma nella realizzazione reale è necessario aggiungere una logica complessa nella funzione "onData" della classe Client. – Janaka

+0

Siamo spiacenti, non capisco la prima parte del tuo commento. Riguardo al tuo secondo, questo si qualifica davvero come una domanda a parte. Suggerirei di rendere privato o protetto il distruttore. – davmac

+0

Ci sarà un'implementazione ingombrante rendendo il distruttore privato o protetto. Quindi cerco un buon design, – Janaka

Problemi correlati