Entra

View Full Version : [C++] Funzioni virtuali


xblitz
07-08-2008, 17:10
Salve a tutti
ho un dubbio sulle funzioni virtuali, riporto ciò che dice il mio libro di testo:

Una funzione virtuale è una funzione che può essere ridefinita nelle sottoclassi solo con lo stesso prottotipo della sua definizione. L'obbiettivo delle funzioni virtuali è quello di non permettere l'overloading di quella funzione nelle sottoclassi [...]

Non mi tornano 2 cose:
primo: quell'overloading non dovrebbe essere overridding?
secondo: perchè allora questo codice funge e il compilatore non mi dice che la funzione è virtual nella superclasse e che non può quindi essere ridefinita con un prototipo diverso?


class prova
{
public:
virtual void funz()
{
cout << "prova";
}
};

class prova2 : public prova
{
public:
virtual void funz(int a)
{
cout << "prova2";
}
};


grazie a tutti!

71104
07-08-2008, 17:20
è normale che qualcosa non ti torni, quella frase è del tutto sballata: l' "obiettivo delle funzioni virtuali" (che espressione idiota) non ha nulla a che vedere con l'overloading che avviene nelle sottoclassi e di certo una funzione virtuale non impedisce l'overload in una sottoclasse di un suo override.

anche la frase precedente mi sembra piuttosto idiota: è stupido dire che in una sottoclasse puoi fare l'override di una funzione usando il prototipo della definizione; la definizione è l'implementazione. puoi anche non aver implementato un certo metodo, ma puoi comunque farne l'override: il programma non linkerà, però compilerà perfettamente.

xblitz
07-08-2008, 17:31
è normale che qualcosa non ti torni, quella frase è del tutto sballata: l' "obiettivo delle funzioni virtuali" (che espressione idiota) non ha nulla a che vedere con l'overloading che avviene nelle sottoclassi e di certo una funzione virtuale non impedisce l'overload in una sottoclasse di un suo override.

ok, ho capito mi sono imbattuto in un altra perla del mio libro di informatica :rolleyes:


anche la frase precedente mi sembra piuttosto idiota: è stupido dire che in una sottoclasse puoi fare l'override di una funzione usando il prototipo della definizione; la definizione è l'implementazione. puoi anche non aver implementato un certo metodo, ma puoi comunque farne l'override: il programma non linkerà, però compilerà perfettamente.
effettivamente :stordita:

... ma allora cosa cavolo fa 'sto virtual? io non l'ho ancora capito :confused:

Ziosilvio
07-08-2008, 18:11
il mio libro di testo
sarà mica il Bullschildt (http://www.catb.org/jargon/html/B/bullschildt.html)?

xblitz
07-08-2008, 18:34
sarà mica il Bullschildt (http://www.catb.org/jargon/html/B/bullschildt.html)?

No: C++ step by step e la cosa che forse vi farà accapponare i capelli è che iol libro è dato in pasto ad un gruppo di studenti di un indirizzo informatico (ITIS) di cui fa parte anche il sottoscritto :sob:

Ziosilvio
07-08-2008, 18:50
No: C++ step by step e la cosa che forse vi farà accapponare i capelli è che iol libro è dato in pasto ad un gruppo di studenti di un indirizzo informatico (ITIS) di cui fa parte anche il sottoscritto :sob:
Va beh, ormai è agosto... quelli della prossima classe li puoi far studiare sull'Eckel che lo possono anche scaricare dal sito dell'autore.

xblitz
07-08-2008, 20:09
Va beh, ormai è agosto... quelli della prossima classe li puoi far studiare sull'Eckel che lo possono anche scaricare dal sito dell'autore.

'spe mi sa che avete frainteso io non sono dall'altra parte della barricata :) devo prendere il diploma quest'anno....

... alla luce di ciò me lo spiegate a che serve questo benedetto virtual? :D

cdimauro
07-08-2008, 20:41
Serve a far abbaiare i cani e a miagolare i gatti: sono entrambi animali, ma hanno un verso... diverso. :p

Ziosilvio
07-08-2008, 20:43
me lo spiegate a che serve questo benedetto virtual?
http://it.wikipedia.org/wiki/Funzione_virtuale

Una classe derivata può invocare metodi della classe base. Questo solleva un'ambiguità, perché non è chiaro a priori se il metodo invocato debba essere trattato come membro della classe base, o come membro della classe derivata.

L'introduzione delle funzioni virtuali in C++ serve a risolvere questa ambiguità.
Una funzione virtuale invocata come metodo della classe derivata, opererà come membro della classe derivata.
Se la funzione non fosse virtuale, verrebbe invocata come membro della classe base.

Nella versione inglese della pagina c'è un esempio molto chiaro in C++.

Bada che altri linguaggi risolvono l'ambiguità in modo diverso.
Per esempio, in Java tutti i metodi sono virtuali, e i metodi della classe base vengono invocati per mezzo della parola chiave super.

71104
07-08-2008, 21:07
@xblitz, ti spiego la metafora di cdimauro con un esempio :D

#include <iostream>
#include <string>
using namespace std;

class Animale
{
public:
virtual string FaiVerso()
{
return "verso generico";
}
};

class Cane : public Animale
{
public:
string FaiVerso()
{
return "bau";
}
};

class Gatto : public Animale
{
public:
string FaiVerso()
{
return "miao";
}
};

void StampaVerso(Animale &animale)
{
cout << animale.FaiVerso() << endl;
}

int main()
{
StampaVerso(Animale());
StampaVerso(Cane());
StampaVerso(Gatto());
return 0;
}


prova ad eseguire il programma due volte, una senza il "virtual" che c'è alla linea 7 e una con, e vedi la differenza.

EDIT - ops, scusate l'esempio è scritto male, un secondo che lo sistemo... :stordita:
EDIT2 - così dovrebbe andare :D

xblitz
07-08-2008, 21:08
Adesso ho capito grazie tante!

Dall'esempio di EN wikipedia ho visto che queste ambiguità si generano solo quando si usano i puntatori, oppure vi sono anche altri casi? a me non ne viene in mente nessun'altro....

71104
07-08-2008, 21:17
Adesso ho capito grazie tante!

Dall'esempio di EN wikipedia ho visto che queste ambiguità si generano solo quando si usano i puntatori, oppure vi sono anche altri casi? a me non ne viene in mente nessun'altro.... vedi il mio esempio: manco un puntatore :O

xblitz
07-08-2008, 21:33
Allora provando l'esempio corretto (quello di prima infatti non mi tornava ma avevo capito dove volevi andare a parare) mi da questo errore:

invalid initialization of non-const reference of type 'Animale&' from a temporary of type 'Animale'

per tutte e tre le funzioni...
passando una copia dell'oggetto (levando quindi l'alias l'oggetto temporaneo viene castato ad animale e mi stampa sempre verso generico).... e qui sono in un vicolo cieco...

71104
08-08-2008, 07:07
curioso, quelle istanziazioni il gcc me le considera const; io avevo compilato col cl, che invece non faceva una piega. mi chiedo quale dei due abbia ragione in base allo standard.

comunque per farlo andare anche sul gcc va modificato così:

#include <iostream>
#include <string>
using namespace std;

class Animale
{
public:
virtual string FaiVerso() const
{
return "verso generico";
}
};

class Cane : public Animale
{
public:
string FaiVerso() const
{
return "bau";
}
};

class Gatto : public Animale
{
public:
string FaiVerso() const
{
return "miao";
}
};

void StampaVerso(const Animale &animale)
{
cout << animale.FaiVerso() << endl;
}

int main()
{
StampaVerso(Animale());
StampaVerso(Cane());
StampaVerso(Gatto());
return 0;
}