Newsgroup: it.comp.lang.c++
Titolo: Meccanismo delle funzioni virtuali

Mi sto scervellando cercandi capire come fa il compilatore a
implementare il sistema delle funzioni virtuali.
Ovvero a grandi linee credo di aver capito ( vedi VTABLE  e puntatore
alla VTABLE) ma in uno specifico caso non riesco proprio a capire come
fa :
 
class base {
public :
void F(void) ;
virtual void F2(void) ;
} ;
 
classe der {
public :
virtual void F(void) ;
} ;
 
base *pb = new der ;
pb->F() ; // chiama base::F() >>>>> perche ?????
 
la VTBALE  di base dovrebbe contenere F2
la VTBALE  di der dovrebbe contenere base::F2 e der::F
 
a questo punto la domanda e' d'obbligo :
ma pb a quale VTABLE accede ? 
 
Mi rispondo : 
alla VTABLE di der (presumo)
 
ma allora perche non trova la der::F ?
 
 
 
 
 
So tutto sulla VTABLE ( tabella delle funzioni virtuali 

 alla VTABLE di der (presumo)
 
presumo anche io ... però non ricordo una cosa, e forse 
sbaglio perché non le uso più da alcuni anni ormai :
ma la catena VIRTUAL, non viene invocata quando non c'è 
nessuna funzione NON-VIRTUAL ? Voglio dire, se si trova un 
match in una funzione non virtual, allora perché consultare 
la VTable ? Dico così eh, solo pensando che si persegua la 
massima efficienza (la chiamata diretta è più veloce).
 
Se ho ragione, allora per implementare la ricerca VTable, 
anche F() di Base dovrebbe essere dichiarata virtual (senza 
= 0, se no non puoi istanziarla)
 
Non so se queste deduzioni siano giuste, giusto ho risposto 
perché se mi corregge qualcuno che è sicuro, colgo 
l'occasione per ripassare pure io :=)
ciao
Soviet


Il 10/01/2012 18:22, xnoise ha scritto:

Come fai a portare un der* in un base* se der non eredita da base ?
 

Come fai a portare un der* in un base* se der non eredita da base ?
 
 classe der  : public base
 
Ok ,
adesso qualcosa eredita,
illuminami.

 illuminami.
 
Quello che hai scritto innanzitutto non compila.
L'attributo "virtual" lo usi per le funzioni nella classe base
non nella derivata.
Se provassi a compilare quello hai scritto il compilatore ti darebbe 
errore: undefined reference to `vtable for der'

Provo a riscrivere quello che posso immaginare intendessi:
 
#include <stdio.h>
 
class base {
public :
	virtual void F(void) {
		printf("base\n");
	}
};
 
class der : public base {
public :
	void F(void) {
		printf("derivata\n");
	}
};
 
int main()
{
	base *pb = new der();
	pb->F();
 
	return 0;
}
 
* in questo caso pb->F() stampa "derivata".
* se invece togli l'attributo virtual alla funzione F nella classe base 
stampa "base".

errore: undefined reference to `vtable for der'
Il tuo forse... io ne ho tre Microsoft e 2 ex Borland e compilano
tutti benissimo.

nessuna funzione NON-VIRTUAL ? Voglio dire, se si trova un 
 
Potrebbe essere.
per esempio qualcosa da qui si capisce su come e' implementata la
VTABLE :
http://en.wikipedia.org/wiki/Virtual_method_table
 
http://www.daniweb.com/software-development/cpp/threads/113056
 
 
ma non riesco a capire fa il compilatore a gestire un caso come quello
da me prospettato che intendiamoci e' corretto ma almeno (per me)
sorprendente.
 
 


F() diventa virtuale in der.
Tu crei un oggetto der, ma lo assegni ad un puntatore a base, in base la 
F() non è virtuale e quindi perché dovrebbe cercare nella vtable?
Ciao

 tutti benissimo.
 
Seee, buonanotte.

F() non � virtuale e quindi perch� dovrebbe cercare nella vtable?
 
Gia,
probabilmente questa informazione il compilatore la deduce subito in
fase di compilazione e genera codice che non accede alla VTABLE.
Se dichiaro virtual la F in base, il compilatore genera codice per
accedere alla VTABLE di "der" e  la chiamata diventa virtuale.

 accedere alla VTABLE di "der" e  la chiamata diventa virtuale.
 
Comunque è un errore concettuale e va contro il principio di 
sostituzione di Liskov.
Un'altra cosa, quando si progetta una classe base, quindi soggetta a 
derivazione e quindi con metodi virtuali, la prima cosa da fare è 
metterci il distruttore virtuale, anche vuoto.
 
Ciao

metterci il distruttore virtuale, anche vuoto.
 
Tralascia la forma  e il punto di vista concettuale.
A me interessa capire come avviene tecnicamente l'implementazione
della chiamata virtuale.
 
Ciao
 
 


Mi sono tolto lo sfizio e preso il  tuo programmino con virtual in 
base::F ma assente in der::F
compilatore g++ sotto ubuntu 11 versione 4.2:
 
 > g++ -g -Wall in.cpp
compila senza warning
 
eseguendo:
 > ./a.out
derivata
 
 
aggiungo il virtual a der::F e lo tolgo a base::F
compila senza warning
 
eseguendo:
 > ./a.out
base
 
Le considerazioni le lascio a voi
 
 
 


No, quel codice non compila. E' impossibile.
Qualsiasi compilatore dovrebbe lamentarsi *almeno* per questa serie di 
motivi:
1 - classe non è una parola chiave
2 - non puoi assegnare un der* a un base*
3 - le varie funzioni F e F2 non sono definite
 
il motivo 1 e 3 sono "triviali" e mi posso immaginare quale sia la cosa 
che avevi in mente
ma il motivo 2 è sostanziale:
provo a buttare li due possibilità:
A - volevi scrivere  class der : public base { al posto di classe der {
e allora non capisco quale sia il problema: stai invocando una funzione 
non virtuale F definita in una classe "base" attraverso un "base*" cosa 
ti aspetti che succeda? io che chiami base::F. Per quale motivo il 
compilatore dovrebbe impelagarsi nella vtable? la vtable viene 
consultata solo per le chiamate virtuali!
 
B - volevi scrivere base *pb = (base*)new der ;  al posto di base *pb = 
new der ;
allora questo è un errore piuttosto grave. la sfortuna è che in certi 
casi potrebbe anche funzionare e potrebbe anche dipendere dall'ordine 
con cui hai dichiarato le funzioni... quindi se vuoi stare tranquillo 
cerca di non usare mai i cast alla C (o il reinterpret_cast) a meno ché 
non sia molto sicuro di quello che stai facendo
 
HTH
 
riporto qui sotto il tuo codice:
