Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1

    [C++] Problema template

    Perchè il seguente programma produce un errore di compilazione?

    Precisamente questo errore (IDE Visual Studio):
    1>Main.obj : error LNK2019: riferimento al simbolo esterno "public: void __thiscall Prova:rint<char>(char)const " (??$print@D@Prova@@QBEXD@Z) non risolto nella funzione _main
    1>c:\users\marco\documents\visual studio 2010\Projects\Prova\Debug\Prova.exe : fatal error LNK1120: 1 esterni non risolti


    codice:
    // Main.cpp
    
    #include "Prova.h"
    
    int main()
    {
    	Prova prova;
    	prova.print( 'a' );
    
    
    	return 0;
    }
    
    
    
    // Prova.h
    
    #ifndef PROVA_H
    #define PROVA_H
    
    
    class Prova
    {
    
    public:
    
    	template <typename T>
    	void print( const T ) const;
    };
    
    
    #endif
    
    
    
    
    // Prova.cpp
    
    #include <iostream>
    using std::cout;
    using std::endl;
    
    
    #include "Prova.h"
    
    
    template <typename T>
    void Prova::print( const T c ) const
    {
    	cout << c << endl;
    }




    L'unico modo per farlo funzionare sembra essere questo (senza utilizzare Prova.ccp), Prova.h si modifica in:

    codice:
    #ifndef PROVA_H
    #define PROVA_H
    
    
    #include <iostream>
    using std::cout;
    using std::endl;
    
    
    
    class Prova
    {
    
    public:
    
    	template <typename T>
    	void print( const T ) const;
    };
    
    
    template <typename T>
    void Prova::print( const T c ) const
    {
    	cout << c << endl;
    }
    
    
    #endif


    Potete spiegarmi le motivazioni di questo comportamento in dettaglio, e/o come risolvere il problema?

    Grazie.

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Dichiarazione e definizione di un template devono essere visibili in ogni unità di compilazione che ne fa uso, altrimenti il compilatore non sa come istanziare il template stesso.
    Il problema si risolve nel modo che hai fatto.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Ma il metodo che ho utilizzato non è decisamente un metodo che consiglierei visto che non consente di separare interfaccia da implementazione, insomma non rispetta le regole di una buona programmazione. Preferirei evitare se possibile, o è davvero l'unica maniera?

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Personalmente ho sempre dubitato di queste fantomatiche: "regole di buona programmazione" da seguire alla lettera. Mi danno l'impressione di essere solo accademia e comunque ognuno ha le sue (e spesso copiate da altri).
    Nel tuo caso hai già separato interfaccia e implementazione.
    codice:
    // Interfaccia
    class Prova
    {
    
    public:
    
    	template <typename T>
    	void print( const T ) const;
    };
    
    // Implementazione.
    
    template <typename T>
    inline void Prova::print( const T c ) const
    {
    	cout << c << endl;
    }
    (Metti inline altrimenti avrai errori di linking se l'unità è inclusa in più unità di compilazione).
    Quello che dici è essenzialmente corretto, ma solo se non si tratta di template. Con i template sei costretto a mettere tutto in un file header; al massimo puoi scrivere l'implementazione in un file che andrà incluso nell'header stesso.
    codice:
     class Prova
    {
    public:
    
        template <typename T>
        void print( const T ) const;
    };
    
    #include "Provaimpl.estensione_a_piacere"
    codice:
    // file Provaimpl.estensione_a_piacere
    template <typename T>
    inline void Prova::print( const T c ) const
    {
        cout << c << endl;
    }
    ma per il compilatore è come scrivere il tutto in un unico file .h
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  5. #5
    Grazie

    Potresti spiegarmi meglio il perchè dell'utilizzo della parola chiave inline?
    Essendo un ".h" non dovrebbe essere di default?

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Se una funzione la dichiari e definisci nel corpo nella classe è inline per default, ma se dichiarata all'interno e definita all'esterno: no.
    Se il template (o qualunque funzione definita in un header file) è incluso in più file, il preprocessore copia-incolla il corpo della funzione nelle varie unità di compilazione, il compilatore compila, ma il linker (che guarda solo la dichiarazione) non sa che la funzione è anche definita e non trovando la definizione in nessun file, da errore.
    Definendo inline la funzione, in pratica dici al linker che oltre che dichiarata, la funzione è anche definita.

    Questo ha un costo ovviamente: se rendi tutto inline, non fai altro che infilare lo stesso codice dappertutto e l'eseguibile ingrassa per niente.
    Questo è inevitabile con i template, però il codice reale di un template viene creato al volo solo quando serve. Nel tuo esempio, se non userai mai la funzione prova della classe, il compilatore non si disturba nemmeno a prenderla in considerazione.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  7. #7
    Utente di HTML.it
    Registrato dal
    May 2008
    Messaggi
    475
    Probabilmente sto per dire una mega-niubbata considerando che in C++ i template li avrò usati una volta, al massimo due, ma...

    Non mi sembra che siano venuti fuori così bene. Casini con la definizione, copia-incolla brutale del codice, il preprocessore che si incasina se non lo metti inline...
    Cioè, l'idea è geniale, ma la realizzazione mi sembra che dia più casini che altro...

    Contano di migliorarli nel C++0x?
    "Let him who has understanding reckon the number of the beast, for it is a human number.
    Its number is rw-rw-rw-."

  8. #8
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Si può pensare a un template come a una grossa macro gestita dal compilatore invece che dal preprocessore. Non se se potessero essere fatti meglio, ma con le mie conoscenze attuali lo escludo. E nel C++0x le cose non sono cambiate. Hanno anche rimosso l'extern, considerato inutile.

    Tra l'altro il problema di linking non è del template in se. Se metti una funzione in un file header, il problema è uguale. Se metti una funzione inline in un .cpp con l'intenzione di esportarla, il problema rimane.
    Il problema di fondo è che il C++ è stato costruito per essere C compatibile, ereditando così tutta la struttura di preprocessing, compiling e linking.
    Probabilmente se Stroustrup non avesse dovuto tener conto di questa possibilità, il C++ sarebbe molto diverso da ciò che conosciamo oggi.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  9. #9
    Originariamente inviato da shodan
    Se una funzione la dichiari e definisci nel corpo nella classe è inline per default, ma se dichiarata all'interno e definita all'esterno: no.
    Infatti.

    Comunque io non ho mai utilizzato la parola chiave inline e fin'ora non ho mai avuto problemi ne con il compilatore ne con il linker, com'è possibile?

  10. #10
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Hai mai incluso una funzione posta in un hreader file in più unità di compilazione?
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.