Newsgroup: it.comp.lang.c++
Titolo: aiuto per principiante

Conosco da tempo il C++, ho letto parecchi libri, ma fino ad ora non
l'avevo mai usato e al primo tentativo ecco li' che salta fuori l'errore.
Il primo programma che ho scritto è un piccolo programma di prova che
riporto.
FILE A.H
class a
{
private:
int val;
public:
a();
void inc();
};
FILE A.CPP
#include "a.h"
inline a::a(){val=0;}
inline void a::inc(){val++;}
FILE TEST.CPP
#include "a.h"
void main()
{
a tmp;
tmp.inc();
}
La compilazione di A.CPP e di TEST.CPP non da' problemi, questi sorgono
con il link, che mi segnala:
Linker Error: Undefined symbol a::inc() in module TEST.CPP
Linker Error: Undefined symbol a::a() in module TEST.CPP
Finora l'unica soluzione che ho trovato e' stata quella di includere in
TEST.CPP anziche' A.H il file A.CPP, che pero' non mi permette di avere un
header ed un file oggeto da distribuire.
Sapete come risolvere questo problema? Grazie in anticipo.

header ed un file oggeto da distribuire.
Certo, perche' includendo A.CPP il compilatore sa come "espandere" le
funzioni "inline".
Ciao, alla prossima.
Angelo.
----------
Rimuovere la protezione anti-spam dall'indirizzo di posta prima di
rispondere. Grazie.
Please remove anti-spam protection from my e-mail address before answering.
Thank you.
----------





Generalmente si usano per brevi funzioni e per questioni di efficienza.
domanda che esula un po' dall'argomento di questo thread: le funzioni
*in-class* sono automaticamente inline? cioe` se la classe:
class a{
private:
	//...
public:	
	sometype DoSomenthing(...){....}  //questa mem fun. e' inline?
	//...
};	
ciao
 Droide.

*in-class* sono automaticamente inline? cioe` se la classe:
Sigh, purtroppo, si`, una sfortunata decisione presa tanto tempo fa da
Stroustrup e ormai necessariamente mantenuta per compatibilita`.
Alex

Sapete come risolvere questo problema? Grazie in anticipo.
Togli gli inline e tutto si risolvera`.  Sono un'ottimizzazione, tutto
sommato, nulla piu`; e per usarli devi essere pronto ad includere
dovunque la classe venga usata anche la definizione dei suoi
inline.  Inoltre ci sono trade-off in termini di aumento del coupling,
possibile espansione del codice, ecc ecc, che non mi sembra
che per un principiante sia il caso di porsi.
Alex

Stroustrup e ormai necessariamente mantenuta per compatibilita`.
ciao Alex, se la cosa non richiede molto tempo, potresti spiegarmi
perche` fu una decisione sbagliata? 
Sono incuriosito anche perche` nella definizione di una classe che
intendo utilizzare per un progettino (ino, ino...), classe dotata di
molte memfun e destinata ad avere moltissime istanze, ho proprio
notato che tutte le memfun sono definite fuori dalla classe e non
inline, anche quelle memfun banali che io, ora come ora, non avrei
esitato a definire inclass. 
Non conosco l'intento dell'autore, ma potrebbe essere stata una scelta
dettata da esigenze diverse da quella della semplice comodità di
stesura del codice?
Ciao,
   Droide.

perche` fu una decisione sbagliata? 
Non ci sarebbe voluto nulla a richiedere l'esplicito aggettivo "inline"
(che comunque e` ammesso, ma non richiesto) per rendere una 
funzione inline, mentre con la scelta in questione non c'e` modo di
avere una funzione scritta entro la classe e NON inline.  Quindi, meno
scelte a disposizione del programmatore.
Rendere una funzione "inline" e` una scelta che va fatta deliberatamente,
come ottimizzazione mirata, e non "per default".
Alex

Ringrazio coloro che mi hanno risposto spiegandomi perche' non 
funzionava. Ora pero' appare un altro problema.
Dopo aver eliminato i due "inline", ricompilando ottengo il seguente
messaggio.
Linker Error: Undefined symbol operator new(unsigned int) in module A.CPP
Cosa e' successo questa volta?

Cosa e' successo questa volta?
Misterioso!  L'operator new(unsigned) dovrebbe venire dalle librerie
standard del C++, e mi sembra improbabile che il linker invocato dal
tuo compilatore non le includa automaticamente -- che ambiente e`?
Alex

 
Si' ma questo non potrebbe creare problemi al compilatore e/o al linker?
Voglio dire, se hai una funzione non inline in un header file incluso da 
piu' moduli (dentro o fuori la dichiarazione della classe fa lo stesso),
o il compilatore e' _molto_ furbo o il linker non manchera' di farti le 
sue rimostranze.
Confesso che i compilatori troppo furbi mi spaventano un pochino, quindi
non sono molto deluso da questa mancata feature. Pero' mi domando se 
esiste un sistema elegante per risolvere il problema (pura curiosita'
accademica).
Antonello
-- 
// ------------------------------------------------------------
// Antonello Salvatucci
// Software Developer, Technical Writer
// LEGO A/S SPU-Darwin, Kloevermarken 120, 7190 Billund DENMARK
// 
// 
+45 75 33 22 33 ext. 5186
       antonello at digi. lego. com

accademica).
Si`, esiste un'ottima soluzione -- non generale al 100% ma praticabile
anche a fronte di linker che di C++ non sappiano nulla (problema,
quest'ultimo, che al giorno d'oggi dovrebbe in effetti risultare una pura
curiosita` accademica, ma che storicamente e` stato importante nella
evoluzione delle implementazioni di C++).
In sostanza, il compilatore deve designare UN file sorgente come "IL"
file ``principale'' che ``implementa la classe'', e solo in quel file allora
il compilatore potra` generare tutto il codice che deve essere presente,
relativamente a quella classe, in 1 sola copia.  L'algoritmo per decidere
quale sorgente e` "il" file principale puo` essere un'euristica qualunque.
Il problema, storicamente, si e` posto per la prima volta relativamente
alla questione: dove mettere la vtable?  i primissimi C-Front ne facevano
copie molteplici, che poi il linker non sapeva semplificare, da cui, spreco
di memoria.  Soluzione: i compilatori piu` recenti usano un'euristica tipo
"implementa la vtable di una classe solo nel sorgente dove si trova la
prima funzione virtuale non in-line della classe".  Non e` al 100% (una
classe puo` anche avere funzioni virtuali solo inline), ma quasi.
Similmente, le funzioni definite in-classe ma non inline potrebbero essere
implementate dal compilatore solo nel sorgente che implementa, della
classe, la prima funzione non in-line e non in-classe, con problemi del
tutto analoghi per classi tali che tutte le loro funzioni sono in-line e/o
in
classe (==nessun file sorgente specificamente associato, solo header).
Naturalmente una soluzione completa richiede un minimo di funzionalita`
del linker (dal quale comunque al giorno d'oggi non si prescinde, pensa
ad esempio al problema di generare e rendere uniche le implementazioni
dei membri dati statici di classi-template...!), o di una fase del
compilatore
che interagisce strettamente con il linker stesso.  Non piu` di quanto possa
servire a un linker in grado di linkare il buon vecchio Fortran, ad esempio
(capacita` di risolvere i "common"...!) -- sembrerebbe ragionevole che a
un linker nel 1998 si chieda quel minimo di funzionalita` indispensabile
per risolvere un costrutto di un linguaggio di 34 anni fa, che ne dici?-)
Alex


Scusate se mi intrometto :-)
Non vedo la necessita' di definire la funzione all'interno del corpo della classe, dove la
piu' piccola modifica costringe a ricompilare tutti i moduli che ne fanno uso.
Semmai, avrei preferito ci fosse la possibilita' di usare funzioni inline gia' compilate,
quindi in moduli separati, il che avrebbe permesso di nasconderne l'implementazione.
L'unico sistema per non avere la funzione inline consiste nel definirla in un file .cpp.
Se proprio si vuole definirla nel file .h, occorre dichiararla virtuale, ma si va da un
eccesso all'altro. Oppure, basterebbe che ci fossero dei cicli o, se non sbaglio degli
switch. In tal caso, il compilatore emette un warning riferendo che non puo' rendere la
funzione inline (ma e' un rimedio peggiore del male, sempre se si puo' considerarlo un
male).
Saluti
Nazzareno
--
Automatic posted from [195.223.93.3]
via Mailgate Server - 
http://www.mailgate.org

 
Gia', questa della v-table l'avevo sentita anch'io. Probabilmente 
non c'e' alternativa migliore (altrimenti qualcuno ci avrebbe 
pensato :). Grazie della delucidazione comunque!
