Newsgroup: it.comp.lang.c++
Titolo: Disastro

Ciao
Allora, premetto innanzitutto di essere agli inizi col c++. Io ho una 
gerarchia di classi. La superclasse si chiama Rectangle ed ha il solo 
compito di costruire una figura rettangolare in base agli argomenti 
ricevuti nel costruttore. Le quattro coordinate vengono salvate nei membri 
xx, xxx, yy, yyy. Inoltre c'é la funzione contains(int x, int y) che 
ritorna true se il punto x, y si trova all'interno dell'area del oggetto.
La subclass si chiama Component. Qui ci sono 2 funzioni virtuali, show() e 
add(). Inoltre é il caso di sottolineare che il costruttore é protected, e 
il suo unico compito é quello di chiamare il costruttore Rectangle e 
passargli le 4 coordinate.
La terza e ultima classe in questione si chiama Button, ed é una subclass 
di Component. L'unico membro della classe é la stringa label. Button 
definisce le funzioni ereditate da Component ed il costruttore, che riceve 
4 coordinate ed una string, inizializza dapprima Component chiamandone il 
costruttore, e poi inizializza la stringa label.
A tutto ció ho aggiunto un main
#include <iostream>
#include "Button.h"
#include "Component.h"
#include "Rectangle.h"
int main(){
	Button b("Hello", 5, 10, 15, 20);
	b.show();
}
Ora il problema é che é un po difficile descrivervi l'errore. La 
compilazione non da errori bensí warnings.
In file included from Button.cpp:1:
Button.h:7: warning: `class Button' has virtual functions but non-virtual
   destructor
Button.cpp: In member function `virtual void Button::add(Component&)':
Button.cpp:19: warning: unused variable `int x'
In file included from main.cpp:2:
Button.h:7: warning: `class Button' has virtual functions but non-virtual
   destructor
main.cpp:9:2: warning: no newline at end of file
Non mi dite che si é costertti a definire un distruttore? Per il momento 
preferirei evitarlo. Poi quello che i preoccupa é l'ultima riga: no newline 
at end of file. Che intende dire?
Vabbé, comunque il vero problema avviene quando cerco di concatenare i 
files .o. Insomma mi si riempie il prompt con strani messagi....alla fine 
comunque il file exe non mi si crea ovviamente. Lo so che forse é una 
spiegazione un po astratta ma forse qualcuno é in grado di aiutarmi a 
verificare l'errore? Grazie.
\alf
-- 
Using M2, Opera's revolutionary e-mail client: 
http://www.opera.com/m2/

 main.cpp:9:2: warning: no newline at end of file
Questo in effetti e' strano, prova a dare un return alla fine del main dopo
la parentesi graffa.
Potresti postare anche i 3 header?
Maurus

 Piuttosto dovresti mettere virtual sul distruttore di Component.
E' meglio che tutti i distruttori siano virtuali (per lo stesso motivo).

 E' meglio che tutti i distruttori siano virtuali (per lo stesso motivo).
se il distruttore è banale o se la classe non viene derivata o se si
è :::sicuri::: che non si userà mai un pointer alla base per distruggere..
non serve a nulla, anzi potenzialmente potrebbe aggiunge overhead..
non credo sia un consiglio da seguire sempre quindi.
sbirish

 virtuali delle classi base.
E perche'?
Se sono sicuro che non derivero' piu' dalla classe derived posso scrivere
anche il metodo senza virtual.
Maurus

 virtuali delle classi base.
Cosa stai dicendo?!?
virtual si eredita, non serve riscriverlo!
Se ho un metodo virtuale nella classe base, NON DEVO dichiarare virtual
tutti gli altri, infatti diventano automaticamente virtuale (scriverlo e'
facoltativo):
Guarda questo codice ed il suo output:
<CODE>
#include <iostream>
class CBase{
public:
    virtual void DisplaySomething(){
        std::cout << "Base class" << std::endl;
    }
};
class CDerived:public CBase{
public:
    void DisplaySomething(){
        std::cout << "Derived class" << std::endl;
    }
};
class CSuperDerived:public CDerived{
public:
    void DisplaySomething(){
        std::cout << "SuperDerived class" << std::endl;
    }
};
void CallDispFunction(CBase &pBase)
{
    pBase.DisplaySomething();
}
int main()
{
    CBase b;
    CDerived d;
    CSuperDerived sd;
    CallDispFunction(b);
    CallDispFunction(d);
    CallDispFunction(sd);
    return 0;
}
</CODE>
<OUTPUT>
Base class
Derived class
SuperDerived class
</OUTPUT>
Come vedi la keyword virtual si trova SOLO nella classe base!
Tommy

sbirish wrote:

OK, se non devo derivare una classe (o se sto costruendo un set di classi in 
modo abbastanza controllato) non metto il distruttore virtuale. Io volevo 
dire che se creo una classe base con alcuni metodi virtuali e (quindi) 
anche il distruttore virtuale, allora anche le classi derivate dovrebbero 
avere il distruttore virtuale.
A priori e' un po' difficile dire che non distruggero' mai la classe da un 
puntatore alla base...
Ma ci sono sempre delle eccezioni alle regole :-)

 anche il metodo senza virtual.
Maurus, non ti capisco, ancora MENO Francesco!
Se nella clase base un metodo e' virtual, anche nelle derivate tale metodo
lo sara', specificando o meno, lo sara' comunque! (quindi Francesco NON ti
capisco!)
Se nella classe base NON e' virtual allora posso decidere se dalla derivata
in poi voglio che lo sia o meno! Non lo deve per forza essere!
Potrei derivare una classe dalla derivata e NON ridefinire tale metodo, nel
qual caso non importa mettere virtual. Se ho intenzione di ridefinirlo,
allora e' bene mettere virtual! Dico e' bene in quanto non e' obbligatorio,
lo diventa se voglio avere il polimorfismo!
Tommy

 cut
Era proprio l'esempio che volevo mostrargli ma poi la pigrizia ha prevalso.
Grazie Tommy.
Maurus

 > anche il metodo senza virtual (nella classe derived, mentre nella classe
base il virtual ci vuole).
Ma penso che si fosse capito dal mio precedente messaggio.
E' chiaro ora?
Maurus

 avere il distruttore virtuale.
Sbagliato!
Se una classe base ha il distruttore virtuale allora anche le derivate lo
avranno che tu lo voglia o no  ;-)
Tommy

 che dalla classe derivata non derivero' ulteriormente.
Dici per leggibilita' allora?!?
Fino a dove ho messo l'asterisco la frase scorre ok! Dopo scorre solo se
parli "per migliorare la leggibilita' del codice".
Oppure, ipotesi piu' probabile, sono io stanco e non ti capisco ;-)
Ad ogni modo ho risposto a te, ma per comodita', volevo solo far notare gli
errori di Francesco.
Tommy

 gli errori di Francesco.
OK OK...
Se leggete il libro di Stroustrup troverete alcuni esempi che danno ragione 
a voi, cioe' e' sufficiente dichiarare "virtual" il metodo della classe 
base affinche' siano tutti quanti "virtual", anche i derivati.
Soltanto mi e' capitato qualche problema qualche tempo fa con un compilatore 
(credo fosse un qualche borland C++) che non aggiornava come avrei voluto 
la tavola delle funzioni virtuali se nelle classi derivate non usavo 
"virtual".
Penso che difficilmente possa capitare una cosa del genere, comunque io 
preferisco sempre specificare il virtual per non avere problemi.
C'e' un'altra ragione, ma e' un po' piu' "filosofica" :-)
L'uso di metodi virtuali e' il qualche caso un po' rischioso, per il 
problema della "fragile base class", quindi in genere preferisco che si 
veda bene quando uno di essi puo' essere ridefinito nelle sottoclassi.
Il problema nasce quando chiamo un metodo virtual foo2() da un altro metodo 
foo1() della stessa classe: quando ridefinisco foo2() cambio il 
comportamento anche di foo1(), senza che si veda dall'interfaccia.
Comunque avete ragione a dire che non e' in generale obbligatorio, io lo 
considero semplicemente una buona regola di programmazione ;-)
Ciao a tutti!

 considero semplicemente una buona regola di programmazione ;-)
Io no! Lo considero SOLO questione di gusti!
Tommy