Può essere corretto derivare da un tipo di libreria standard violando anche il principio di Liskov?

7

Vorrei definire un puntatore condiviso il cui operator== confronta il puntato con valori al posto dei puntatori, qualcosa del genere:

template <typename T>
struct deref_shared_ptr: std::shared_ptr<T> {
    bool operator==(const deref_shared_ptr rhs) const { 
        return (**this == *rhs);
    }
};

Questo tipo ha due potenziali problemi:

  • Deriva da un tipo di libreria standard.

  • Violare il principio di sostituzione di Liskov, poiché cambia la semantica di operator== .

Tuttavia, sto pensando che nessuno dei due è un problema a meno che non si usi il puntatore / riferimento di tipo base per riferirsi al tipo derivato. In particolare, questi problemi potrebbero non verificarsi mai nel codice del modello. Per i puntatori condivisi, la situazione è ancora migliore: i puntatori condivisi vengono memorizzati e passati per valore.

La mia logica è corretta? Ci sono ancora dei buoni motivi per evitare la definizione di cui sopra a favore della composizione?

    
posta AlwaysLearning 29.07.2016 - 09:51
fonte

1 risposta

12

Non dirò che la tua logica è decisamente sbagliata, ma mi dà una sensazione di nausea - ad es. cosa succede se qualcuno lo usa accidentalmente come shared_ptr comunque?

In questo tipo di situazione creo la mia classe che contiene il shared_ptr . Per es.

class CustomPtr {
    shared_ptr<XType> m_xp;
public:
    ... some stuff ....
    operator bool()const{return (bool)m_xp;}
    void reset() {m_xp.reset();}

    Transport *operator->(){return m_xp.get();}
    const Transport *operator->()const{return m_xp.get();}
    ... more stuff ....
};

Devo proxy o altrimenti avvolgere qualsiasi interfaccia che voglio usare - ma considero questo un vantaggio. In genere utilizzo solo una manciata di metodi di accesso e mi piace essere sicuro che nessuno stia utilizzando metodi inaspettati.

    
risposta data 29.07.2016 - 10:50
fonte

Leggi altre domande sui tag