ciao a tutti, sempre sulle liste, poichè creando la classe lista con le funzioni virtuali pure ho avuto problemi di compilazione, ho deciso di renderle non pure. diciamo che va un po' meglio però mi da un errore sulle funzioni virtuali. posto la classe lista (con la relativa classe derivata) e il test della lista.

lista.h
codice:
#include <iostream>
#include <stdlib.h>

using namespace std;

template<class posizione, class tipoelem>
class lista
{
   public:
      virtual void crealista();
      virtual bool listavuota();
      virtual posizione primolista();
      virtual bool finelista(posizione);
      virtual posizione succlista(posizione);
      virtual posizione predlista(posizione);
      virtual tipoelem leggilista(posizione);
      virtual void scrivilista(posizione, tipoelem);
      virtual void inslista(posizione, tipoelem);
      virtual void canclista(posizione);
      
      void stampalista();
      void fondiordinate(lista &, lista &);
      void epurazione();
      void naturalmergesort();
   private:
      void distribuisci(lista &, lista &);
      void copiacatena(posizione, lista &, posizione, lista &);
      void copia(posizione, lista &, posizione, lista &, bool *);
      void merge(lista &, lista &, lista &, int *);
      void fondicatena(posizione, lista &, posizione, lista &, posizione, lista &);
      
};

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::stampalista()
{
   posizione p = primolista();
   while(!finelista(p))
   {
      cout << leggilista(p) << "\n";
      p = succlista(p);
   }
   cout << "\n";
}
   

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::fondiordinate(lista<posizione, tipoelem> &A, lista<posizione, tipoelem> &B)
{
   posizione pa = A.primolista();
   posizione pb = B.primolista();
   posizione pc = primolista();
   
   tipoelem elem1 = A.leggilista(pa);
   tipoelem elem2 = B.leggilista(pb);
   while(!A.finelista(pa) && !B.finelista(pb))
   {
      if(elem1 <= elem2)
      {
         inslista(pc, elem1);
         pa = A.succlista(pa);
      }
      else
      {
         inslista(pc, elem2);
         pb = B.succlista(pb);
      }
      elem1 = A.leggilista(pa);
      elem2 = B.leggilista(pb);
   }
   while(!A.finelista(pa))
   {
      inslista(pc, elem1);
      pa = A.succlista(pa);
      elem1 = A.leggilista(pa);
   }
   while(!B.finelista(pb))
   {
      inslista(pc, elem2);
      pb = B.succlista(pb);
      elem2 = B.leggilista(pb);
   }
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::epurazione()
{
   posizione p = primolista();
   posizione q;
   posizione t;
   while(!finelista(p))
   {
      q = succlista(p);
      while(!finelista(q))
      {
         if(leggilista(p) == leggilista(q))
         {
            t = succlista(q);
            canclista(q);
            q = t;
         }
         else
            q = succlista(q);
      }
      p = succlista(p);
   }
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::naturalmergesort()
{
   int numerocatene;
   lista<posizione, tipoelem> A, B, L;
   do
   {
      A.crealista();
      B.crealista();
      distribuisci(A, B);
      numerocatene = 0;
      crealista();
      merge(A, B, L, &numerocatene);
   }while(numerocatene != 1);
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::distribuisci(lista<posizione, tipoelem> &A, lista<posizione, tipoelem> &B)
{
   posizione p = primolista();
   posizione pa = A.primolista();
   posizione pb = B.primolista();
   do
   {
      copiacatena(p, *this, pa, A);
      if(!finelista(p))
         copiacatena(p, *this, pb, B);
   }while(!finelista(p));
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::copiacatena(posizione p, lista<posizione, tipoelem> &L, posizione pa, lista<posizione, tipoelem> &A)
{
   bool finecatena = false;
   do
      copia(p, L, pa, A, &finecatena);
   while(!finecatena);
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::copia(posizione p, lista<posizione, tipoelem> &L, posizione pa, lista<posizione, tipoelem> &A, bool *finecatena)
{
   bool esito = *finecatena;
   finecatena = &esito;
   tipoelem elemento = leggilista(p);
   A.inslista(pa, elemento);
   p = succlista(p);
   pa = succlista(pa);
   if(finelista(p))
      esito = true;
   else
      esito = (elemento > leggilista(p));
   finecatena = &esito;
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::merge(lista<posizione, tipoelem> &A, lista<posizione, tipoelem> &B, lista<posizione, tipoelem> &L, int *numcatene)
{
   posizione p = primolista();
   posizione pa = A.primolista();
   posizione pb = B.primolista();
   
   while(!A.finelista(pa) && !B.finelista(pb))
   {
      fondicatena(pa, A, pb, B, p, L);
      numcatene++;
   }
   while(!A.finelista(pa))
   {
      copiacatena(pa, A, p, L);
      numcatene++;
   }
   while(!B.finelista(pb))
   {
      copiacatena(pb, B, p, L);
      numcatene++;
   }
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::fondicatena(posizione pa, lista<posizione, tipoelem> &A, posizione pb, lista<posizione, tipoelem> &B, posizione p, lista<posizione, tipoelem> &L)
{
   bool finecatena = false;
   do
   {
      if(A.leggilista(pa) < B.leggilista(pb))
      {
         copia(pa, A, p, *this, &finecatena);
         if(finecatena)
            copiacatena(pb, B, p, *this);
      }
      else
      {
         copia(pb, B, p, *this, &finecatena);
         if(finecatena)
            copiacatena(pa, A, p, *this);
      }
   }while(finecatena);
}
listap.h
codice:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include "lista.h"
#include "nodop.h"

using namespace std;

template<class tipoelem>
class listap : public lista<nodop<tipoelem> *, tipoelem>
{
   public:
      typedef nodop<tipoelem> *posizione;
      listap();                             //costruttore di default
      void crealista();                     //crea la lista vuota
      bool listavuota();                    //stabilisce se la lista è vuota o meno
      posizione primolista();               //restituisce la posizione del primo elemento della lista
      bool finelista(posizione);            //stabilisce se il nodo è l'ultimo della lista
      tipoelem leggilista(posizione);       //restituisce l'elemento della posizione specificata
      posizione succlista(posizione);       //restituisce la posizione del nodo successivo 
      posizione predlista(posizione);       //restituisce la posizione del nodo precedente
      void scrivilista(posizione, tipoelem);//scrive l'elemtno nel nodo specificato dalla posizione
      void inslista(posizione, tipoelem); //inserisce un nodo e scrive l'elemento nella posizione specificata 
      void canclista(posizione);          //elimina il nodo nella posizione specificata
   private:
      nodop<tipoelem> cella;                 //nodo della lista (nodo sentinella)
};

template<class tipoelem>
listap<tipoelem>::listap()
{
   crealista();                             //il costruttore invoca il metodo crealista
}

template<class tipoelem>
void listap<tipoelem>::crealista()
{
   cella.setprec(&cella);
   cella.setsuc(&cella);
   cella.setelem(0);
}

template<class tipoelem>
bool listap<tipoelem>::listavuota()
{
   return((cella.getprec() == &cella) && (cella.getsuc() == &cella));
}

template<class tipoelem>
typename listap<tipoelem>::posizione listap<tipoelem>::primolista()
{
   return(cella.getsuc());
}

template<class tipoelem>
bool listap<tipoelem>::finelista(typename listap<tipoelem>::posizione pos)
{
   return(pos == &cella);
}

template<class tipoelem>
tipoelem listap<tipoelem>::leggilista(typename listap<tipoelem>::posizione pos)
{
   return(pos->getelem());
}

template<class tipoelem>
void listap<tipoelem>::scrivilista(typename listap<tipoelem>::posizione pos, tipoelem elem)
{
   pos->setelem(elem);
}

template<class tipoelem>
typename listap<tipoelem>::posizione listap<tipoelem>::succlista(typename listap<tipoelem>::posizione pos)
{
   return(pos->getsuc());
}

template<class tipoelem>
typename listap<tipoelem>::posizione listap<tipoelem>::predlista(typename listap<tipoelem>::posizione pos)
{
   return(pos->getprec());
}

template<class tipoelem>
void listap<tipoelem>::inslista(typename listap<tipoelem>::posizione pos, tipoelem elem)
{
   posizione temp = new nodop<tipoelem>;
   
   temp->setprec(pos->getprec());
   temp->setsuc(pos);
   (pos->getprec())->setsuc(temp);
   pos->setprec(temp);
   temp->setelem(elem);
   pos = temp;
}

template<class tipoelem>
void listap<tipoelem>::canclista(typename listap<tipoelem>::posizione pos)
{
   posizione temp = pos;
   (pos->getsuc())->setprec(pos->getprec());
   (pos->getprec())->setsuc(pos->getsuc());
   pos = pos->getsuc();
   delete temp;
}
testlista.cpp
codice:
#include "listap.h"
#include <iostream>
#include <stdlib.h>

using namespace std;

int main()
{
   listap<int> list, list2, list3, list4;
   listap<int>::posizione pos = list.primolista();
   listap<int>::posizione pos2 = list2.primolista();
   listap<int>::posizione pos4 = list4.primolista();
   int k;
   
   for(int i = 0; i < 10; i++)
   {
      list.inslista(pos, (100 - (i * 10)));
      pos = list.primolista();
   }
   
   for(int i = 0; i < 10; i++)
   {
      list2.inslista(pos2, (50 - (i * 5)));
      pos2 = list2.primolista();
   }

   list.stampalista();
   list2.stampalista();
   
   cout << "\n\n";
      
   list3.fondiordinate(list, list2);
   list3.stampalista();
   cout << "\n\n";
   list3.epurazione();
   list3.stampalista();
   
   cout << "\n\n";
   for(int i = 0; i < 10; i++)
   {
      cin >> k;
      list4.inslista(pos4, k);
      pos2 = list2.primolista();
   }
   list4.stampalista();
   list4.naturalmergesort();
   cout << "\n\n";
   list4.stampalista();
   
   system("pause");
   return 0;
}
l'errore è il seguente:

[Linker error] undefined reference to `lista<nodop<int>*, int>::scrivilista(nodop<int>*, int)'


in pratica mi dà una lista di quell'errore per ogni metodo virtuale. cosa c'è che non va?
eppure i metodi virtuali vengono implementati nella classe derivata!!!