Newsgroup: it.comp.lang.c++
Titolo: Ereditare i costruttori.

C'e` un modo per richiamare il costruttore di una classe ereditata?
Per esempio:
Sia A la classe:
class A {
	public:
		A(int n=0) {a=n;}
		int leggi() const {return a;};
		void scrivi(int n) {a=n;};
	private:
		int a;
	};
Ora voglio costruire una classe B che si limiti ad aggiungere un metodo a
quelli gia` specificati per A.
class B : public A {
	public:
		void somma(int n) { scrivi(leggi()+n); };
	};
A questo punto la classe B fa tutto quello che faceva A tranne qualcosa
del tipo "B b(10);".
C'e` un modo per richiamare il costruttore di A?
Se dovessi riscrivere un costruttore sarei costretto ad utilizzare la
funzione "scrivi" perche a e` privato di A.
E se "scrivi" non esistesse? Ho altre soluzioni per aggiungere il metodo
somma e costruire una nuova classe? 
Ovviamente in tutto questo assumo di non modificare la definizione di A.
Cordialita`,
Marco Pastrello
pa...@dei.unipd.it
marco.p...@pd.nettuno.it

Ciao Marco,
questa e' la sintassi per richiamare il costruttore di una classe base:
class A {
 public:
 A(int n=0) {a=n;}
 int leggi() const {return a;};
 void scrivi(int n) {a=n;};
 private:
 int a;
 };
class B : public A {
 public:
 B(int n=0);
 void somma(int n) { scrivi(leggi()+n); };
 };
/* costruttore di B che richiama quello della classe base A */
B::B(int n=0) : A(n)
{
}
ciao, Franco.
Franco Torrini - Software Engineer - 
f.to...@virtuart.it
VIRTUART - C.C.D. Creative Computer Design S.p.A.
Via di Quarto Annunziata, 80/b - 00189 Rome, Italy
Tel. 
+39 06 33076638
 - Fax. 
+39 06 33076670
Marco Pastrello wrote in message <6tk1d1$1fd$1...@burp.localdomain>...


C'e` un modo per richiamare il costruttore di A?
Aggiungi alla classe B il seguente costruttore:
    B(int n=0): A(n) {}
Questa e' la sintassi di "ctor-initializer-list": il costruttore di una
classe (nella sua definizione, non nella dichiarazione -- lo chiarisco
perche' qui, con il ctor inlinea, le due cose si possono confondere)
puo' avere, dopo la ")" che termina l'eventuale elenco degli argomenti,
un ":", poi un elenco di costruttori separati da virgole (qui di virgole
non ne vedi perche` abbiamo un solo inizializzatore!) che permettono
di usare costruttori non-default per tutte le basi e i membri della
classe stessa.
E' un tipico errore da principiante, e potenzialmente molto grave
(Lippman lo identifica come il piu` frequente...!), scrivere cose come:
    class UnaClasse {
        AltraClasse xxx;
    public:
        UnaClasse(int x) {
            xxx = espressione;
        }
    };
Questo costruisce anzitutto xxx col suo costruttore di default
(prima operazione potenzialmente costosa), poi, nel corpo del
costruttore di UnaClasse, costruisce un temporaneo di tipo
AltraClasse basato sulla espressione (seconda operazione
potenzialmente costosa) e infine sovrascrive xxx chiamando
l'operatore di assegnazione di AltraClasse col temporaneo
(terza operazione potenzialmente costosa).
La forma giusta e' invece sempre:
        UnaClasse(int x): xxx(espressione) {}
che esegue UNA sola operazione potenzialmente costosa (ma
d'altronde inevitabile: il costruttore di AltraClasse bene o male
dev'essere fatto) invece di TRE.
E' bene abituarsi a usare SEMPRE la sintassi "ctor-init-list" ed
evitare come la peste le assegnazioni nel corpo del costruttore;
non sempre questo migliora le prestazioni, ma non le peggiora
mai, e una volta presa l'abitudine l'erroraccio-da-principiante di
cui sopra non capitera' piu'.
Attenzione a una cosa: l'ORDINE in cui vengono eseguiti gli
inizializzatori NON e' quello in cui vengono scritti nella lista,
bensi' e' sempre l'ordine canonico: prima tutte le basi (da
sinistra a destra nell'elenco di derivazione in caso di eredita`
multipla), poi tutti i membri ("dall'alto in basso" nell'ordine in
cui sono dichiarati nella classe).  Questo permette piu` avanti
al distruttore della classe di distruggere ogni cosa nell'ordine
giusto, cioe` esattamente nell'ordine inverso a quello in cui
le cose sono state costruite.
Questo non causa problemi se lo si tiene presente; basta, al
limite, dichiarare le basi e i membri della classe nell'ordine
"giusto" nei rari casi in cui l'ordine di inizializzazione risulti
effettivamente importante!
Alex