Sfondo
Sto scrivendo una classe di gestione delle immagini. Per questa domanda sono interessanti due requisiti della classe:
- Deve avere una "const" correttezza.
- Deve consentire che gli alias delle immagini secondarie, le sezioni a.k.a. o l'affettatura, senza eseguire copie approfondite dei dati di immagine.
Per profonda costanza intendo il seguente. Considera questa classe di esempio:
class Image{
public:
...
Image(const Image&);
Image alias(int x0, int y0, int x1, int y1) const;
private:
Buffer image_data;
};
Supponiamo che tu abbia una funzione che ha passato un riferimento const a un'immagine, in questo modo:
void foo(const Image& im){
Image alias = im.alias(0,0, 10, 10);
// Hold on, the mutable alias can modify the data in the const argument!
}
La chiamata alla funzione alias
sopra sconfigge la costanza dell'argomento perché il contenuto dell'immagine dell'argomento può essere modificato tramite l'alias non const. Non posso restituire un const Image
da alias
perché in realtà non ha senso e il costruttore di copie di Image
costruirà comunque un'istanza mutabile.
La mia soluzione (e l'ho vista spesso usata così non rivendico l'originalità qui) è di introdurre due classi (le interfacce in realtà, ma per la semplicità sono classi in questo esempio e il ritorno per valore è ok, in reality alias(...)
restituisce un shared_ptr
all'interfaccia):
class ConstImage{
public:
ConstImage alias(...) const;
};
class Image{
public:
Image alias(...);
};
Ora il seguente codice:
void foo(const Image& im){
// compile error, cannot convert ConstImage to Image, perfect!
Image alias = im.alias(...);
}
E ovviamente cambieresti la firma in void foo(const ConstImage& im)
in modo che tu possa accettare invocazioni come foo(const_im.alias(...))
o altri oggetti ConstImage
.
Ora ovviamente vogliamo che foo(const ConstImage& im)
sia callable (1) con un% mutabile% co_de e qui è dove arriva la domanda.
Domanda
Utilizzo dell'ereditarietà: Image
renderà tutti i tipi class Image : public ConstImage
utilizzabili tramite Image
riferimenti e puntatori. Faciliterà anche il riutilizzo del codice tra le implementazioni const e non const che per necessità sono molto simili.
Questo risolve il problema sopra menzionato (1). Tuttavia, se si considera la relazione di ereditarietà come un'istruzione "è una", allora "un'immagine mutevole è un'immagine immutabile" non ha senso. Che parla contro l'utilizzo dell'eredità qui.
La mia domanda è, questo tipo di (ab) uso dell'eredità è ampiamente accettabile? C'è qualche altra soluzione migliore che ho trascurato? Si noti che la classe ConstImage
è più un'interfaccia, quindi non è possibile la conversione del valore naive da Image
a Image
. Anche se uno potrebbe probabilmente inventarsi qualcosa di pazzo per consentirlo.