Accesso alla catena o restituire il valore del puntatore privato

1

si spera che il titolo non sia troppo confuso, sto avendo problemi a pensare a ciò che le migliori pratiche mi dicono di fare in questa situazione.

Dire che ho la seguente struttura di classe

Class A {
public:
    bool isCompressed() { return compressed_; }
private:
    bool compressed_;
}

Class B {
private:
    ClassA *a_ptr_;
public:
    /* Accessor here */
}

Se dovessi avere accesso alla variabile compressed_ in ClassA all'interno di un'implementazione con un oggetto ClassB dovrei avere un accesso come questo:

ClassA* ClassB::filePointer() const {
    return a_ptr_;
}

e implementazione di

if (objectA.filePointer()->isCompressed()) { ... }

o questo:

bool ClassB::isFileCompressed() const { 
    return a_ptr_->isCompressed(); 
}

e implementazione di

if (objectB.isFileCompressed()) { ... }

Mi rendo conto che potrebbe trattarsi di una questione di best practice (o forse non lo è ...?), ma si spera che possa dirmi in quale direzione si dovrebbe andare a riguardo!

Grazie!

    
posta wKavey 16.06.2016 - 06:40
fonte

1 risposta

1

Restituire un puntatore privato è una cattiva idea?

Rendendo un membro privato, esprimi che questa è l'attività interna della classe, e che vuoi avere la libertà di gestire tali settori come desideri.

Il problema quando si restituisce un puntatore privato, si dà il controllo, rompendo la propria intenzione di progettazione:

  • Che cosa succede se il chiamante cancella il puntatore, accidentalmente pensando che si trattava di un puntatore da copiare per uso personale?
  • Cosa succede se il chiamante richiama membri dell'oggetto appuntito che alterano il suo stato (ad esempio chiudi il file, mentre la tua classe B assume che rimanga aperto)?
  • Cosa succede se il chiamante memorizza una copia del puntatore e la usa in un secondo momento? Soprattutto se hai cancellato l'oggetto nel frattempo?

Potresti sperare che l'aggiunta della parola chiave const eviti questi problemi. Sfortunatamente A* B::filePointer() const {...} significa semplicemente che questa funzione membro non cambia lo stato dell'oggetto B.

Potresti mitigare un po 'i rischi, rendendolo const A* B::filePointer() const {...} . In questo modo, il chiamante può solo invocare funzioni membro const sul puntatore del file e assegnarlo con un puntatore a const. Sfortunatamente, ciò non impedirà la cancellazione accidentale.

Demo online del problema

L'altro svantaggio è che i consumatori di classe B dipendono anche dagli interni di quella classe. Questo non rispetta il principio di.

Incapsulamento e separazione delle preoccupazioni

La tua alternativa "accessoria concatenata" sembra molto meglio:

  • utilizza incapsulamento in modo efficace per nascondere completamente i dettagli di implementazione. Se domani preferisci utilizzare un flusso invece di una classe A, puoi farlo: il mondo esterno alla classe B non deve sapere nulla del tuo cambiamento.
  • promuove separazione delle preoccupazioni : la classe B non deve sapere nulla sull'interno della classe A, perché utilizza solo un membro pubblico. E il mondo esterno non deve sapere nulla degli interni di classe B, e quindi non dipende dalla classe A.
risposta data 17.06.2016 - 21:32
fonte

Leggi altre domande sui tag