I linguaggi di programmazione più orientati agli oggetti, come il Java o il C#, utilizzano la classe Object come classe base astratta da cui derivano automaticamente tutte le classi che vengono create. Nel c++ questo approccio è meno diretto, in quanto quando viene creata una classe questa non deriva da nessun’altra classe. Ciò permette al c++ di essere più ottimizzato e permette al programmatore di scegliere l’approccio che più preferisce all’interno del proprio progetto: Se questo è un progetto semplice si possono utilizzare le classi senza grandi problemi, altrimenti conviene crearsi una propria Abstract Base Class (per gli amici ABC) da cui derivare tutte le proprie classi.

Abstract Base Class

I vantaggi nell’utilizzo di una classe ABC sono molteplici: se tutte le classi derivano da una classe base, possiamo sempre castarle alla classe base, possiamo avere dei metodi di debug in comune tra tutte le classi del nostro progetto, e se attiviamo l’RTTI possiamo facilmente capire a che classe appartiene un determinato oggetto.

Uno dei classici esempi di utilizzo è quello di costruire un array di oggetti che derivano dalla nostra classe base, e poter utilizzare su questi oggetti i metodi della classe base senza problemi.

Abstract Base Class Array

Adesso passiamo al codice vero e proprio.

Per realizzare la nostra bellissima ABC, che ovviamente chiameremo Object, ci basterà scrivere qualcosa del genere nel file .h:

Object.h

class Object {
public:
	// distruttore virtuale
	virtual ~Object() {}
	// metodo virtuale per ottenere le informazioni di debug su un oggetto
	virtual const String getDebugInfo() const = 0;
};

La classe Object utilizza la classe String, che verrà implementata in un altro articolo.

La parola chiave virtual sta a indicare che stiamo dichiarando una funzione virtuale, ovvero una funzione di cui l’implementazione è conosciuta dal compilatore a run-time: in pratica quanto istanzieremo un oggetto di una classe derivata da Object e verrà invocato getDebugInfo() il metodo virtuale utilizzato sarà quello della classe istanziata, e non quello della classe base.
const sta a significare che il metodo è costante, ovvero che non può modificare i dati della classe (non avrebbe molto senso fare un metodo che stampa le informazioni di debug su una classe e poi ne modifica il contenuto).
Infine, = 0 indica che il metodo non è implementato in questa classe, ovvero che la classe è abstract, e deve essere necessariamente implementato dalle classi derivate. Se una classe ha un metodo abstract, questa classe non potrà mai essere creata direttamente.

Siccome la nostra classe Object ha un metodo abstract, questa non potrà mai essere istanziata con “Object * o = new Object()“, al massimo è possibile assegnare a questa il riferimento ad un oggetto di una classe figlia di Object.

Al codice sorgente ho aggiunto queste riga di codice, che ci permettono di usare l’oggetto cout sulla nostra classe Object:

Object.h

ostream &operator<<(ostream & out, const Object & obj);

Object.cpp

ostream & operator<<(ostream & out, const Object & obj) {
out<<obj.getDebugInfo();
return out;
}

E quindi basterà fare qualcosa del genere:

String * str = new String(”pino”);
cout<<str

Per mandare in output le informazioni di debug sulla nostra classe!
Se si derivano quindi tutte le classi del nostro progetto dalla classe Object, implementando in questa un paio di funzioni di utilità generale, possiamo quindi ottenere il controllo totale delle nostre classi, e gestire facilmente i cast, le liste e il debug!

Download Object ABC. Downloads: 88


Se sei interessato a questo post, potresti anche provare a leggere:

    No related posts