|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Junior Member
Iscritto dal: Mar 2008
Messaggi: 10
|
[c++]template di classe
Buonasera. Ho un piccolo problema da esporre. Ho questa classe:
Codice:
#ifndef ATTRIBUTOVALORE_H #define ATTRIBUTOVALORE_H #include "string.h" using namespace std; template <class T> class AttributoValore{ public: AttributoValore(T,string); ~AttributoValore(); bool setAttribute(string Attribute); bool setValue(T Value); T getValue(); string getAttribute(); private: T value; string attribute; }; #endif Codice:
#ifndef FATTO_H #define FATTO_H #include <list> #include <string> #include "attributovalore.h" using namespace std; class Fatto { public: Fatto(AttributoValore AV); ~Fatto(); bool setFactName(string name); bool addAttVal(AttributoValore AV); private: string Name; list<AttributoValore> Attributi; }; #endif ![]() |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Oct 2002
Città: San Jose, California
Messaggi: 11794
|
Quando usi la classe parametrica devi indicare al compilatore che tipo vuoi:
AttributoValore<int> AttributoValore<char> AttributoValore<MyClass> In questo modo il compilatore e' in grado di generare una classe completa usando rispettivamente int, char o MyClass al posto di T. Inoltre devi dichiarare tutti i metodi della classe template inline nel .hpp di modo che il compilatore li abbia disponibili al momento dell'instanziazione del template. Ti stai andando a cacciare in un grosso guaio con i template, occhio.
__________________
"We in the game industry are lucky enough to be able to create our visions" @ NVIDIA |
![]() |
![]() |
![]() |
#3 |
Junior Member
Iscritto dal: Mar 2008
Messaggi: 10
|
quindi devo per forza già dire adesso quale sarà il tipo T, e non c'è un modo per dirlo successivamente?
comunque adesso ho modificato la classe cosi Codice:
#ifndef FATTO_H #define FATTO_H #include <list> #include <string> #include "attributovalore.h" using namespace std; typedef AttributoValore <int> AttributoV; class Fatto { public: Fatto(AttributoV AV); ~Fatto(); bool setFactName(string name); bool addAttVal(AttributoV AV); private: string Name; list<AttributoV> Attributi; }; #endif Codice:
C:\Documents and Settings\Teddy\Documenti\Università\ICSE\Interprete\fatto.o(.text$_ZSt8_DestroyI15AttributoValoreIiEEvPT_[void std::_Destroy<AttributoValore<int> >(AttributoValore<int>*)]+0xd) In function `ZNSt10_List_baseI15AttributoValoreIiESaIS1_EE11_M_get_nodeEv': [Linker error] undefined reference to`AttributoValore<int>::~AttributoValore()' |
![]() |
![]() |
![]() |
#4 | ||
Senior Member
Iscritto dal: Oct 2002
Città: San Jose, California
Messaggi: 11794
|
Quote:
Quote:
Esempio: Codice:
class MyFirstTemplate<typename T> { MyFirstTemplate() { // initialise class here } T Get(T& x) const { return x; } }; void main() { MyFirstTemplate<int> object_of_int; // instatiate MyFirstTemplate<int> here (well, a bit above) assert(5 == object_of_int.Get(5)); // works!? }
__________________
"We in the game industry are lucky enough to be able to create our visions" @ NVIDIA Ultima modifica di fek : 21-03-2008 alle 17:35. |
||
![]() |
![]() |
![]() |
#5 |
Junior Member
Iscritto dal: Mar 2008
Messaggi: 10
|
Ho capito la questione dei template.
Per quanto riguarda il codice avevo già implementato i metodi: della prima classe Codice:
#include <iostream> #include "attributovalore.h" #include "string.h" using namespace std; template <class T> AttributoValore<T>::AttributoValore(T valore, string attributo) { value=valore; attribute=attributo; } template <class T> AttributoValore<T>::~AttributoValore(){ cout<<"Coppia attributo-valore eliminata\n"; } template <class T> bool AttributoValore<T>::setAttribute(string Attribute) { attribute=Attribute; if (attribute=="") return false; else return true; } template <class T> bool AttributoValore<T>::setValue(T Value) { value=Value; if (value=="") return false; else return true; } Codice:
#include "fatto.h" #include <string> #include <list> #include <iostream> #include "attributovalore.h" using namespace std; Fatto::Fatto(AttributoV AV){ Attributi.push_front(AV); } Fatto::~Fatto(){ cout<<"Fatto eliminato\n"; } bool Fatto::addAttVal(AttributoV AV) { Attributi.push_front(AV); if(Attributi.empty()) return true; else return false; } bool Fatto::setFactName(string name) { Name=name; if(Name=="") return false; else return true; } |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Oct 2002
Città: San Jose, California
Messaggi: 11794
|
No, il problema e' che devi implementare i metodi inline come ho fatto io nel mio esempio. Il compilatore deve avere l'intera definizione della classe e dei suoi metodi in ogni unita' di traslazione che istanzia un template. Tante parole difficili per dire: definisci i metodi della classe template inline nel file .h, includilo dove usi la classe template, e funzionera' tutto.
__________________
"We in the game industry are lucky enough to be able to create our visions" @ NVIDIA |
![]() |
![]() |
![]() |
#7 | |
Junior Member
Iscritto dal: Mar 2008
Messaggi: 10
|
Quote:
|
|
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Sì...questo perché le classi relative ai vari tipi di dati vengono generate in fase di compilazione.
|
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Oct 2002
Città: San Jose, California
Messaggi: 11794
|
Quote:
Il processo si chiama istanziazione di un template: ogni volta che indichi esplicitamente i tipi associati ad una classe template, il compilatore crea letteralmente il codice di una nuova classe in quel punto (un po' prima in realta') e relativi metodi, sostituendo letteralmente ai tipi parametrici i tipi reali che hai indicato. Per fare questo ha bisogno di tutte le informazioni della classe template, quindi di tutte le dichiarazioni e tutti i metodi implementati.
__________________
"We in the game industry are lucky enough to be able to create our visions" @ NVIDIA |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 13:52.