Klasa abstrakcyjna, templaty i polimorfizm

0

Hej,

Nie jestem programistą c++ dlatego bardzo liczę na Waszą pomoc.
Mam stworzyć klasę która ma działać jako "double linked ring", i klasa ta ma być oparta na szablonach (template). Jest zdefiniowana tak:

template <typename T>
class DLRing{

};

czyli jest to lista, która przechowuje dowolnej klasy parametry. Chciałam żeby ta klasa miała metodę sortuj. I teraz chciałabym zostawić użytkownikowi, który teoretycznie będzie korzystał z tej metody czy ma być to sortowanie w kierunku malejącym, czy rosnącym czy jakim sobie wymyśli. Dlatego funkcja sortuj przyjmuje jako parametr stworzoną przeze mnie klasę Comparator

void sort(Comparator<T> c);

Chciałabym żeby klasa Comparator była tylko interfejsem, żeby nie można było stworzyć egzemplarza tej klasy, a tylko klasy po niej dziedziczące implementowały
odpowiednie metodę, która jest używana w funkcji sort. Chciałam skorzystać z poliformizmu - żeby wywoływana była metoda z "klasy dziecka" Dlatego napisałam takie 2 klasy:

template <typename T>
class Comparator{
      public :
             int virtual  compare(T data1, T data2)=0;
      };


template <typename T>
class AscendingOrderComparator : public Comparator<T>{
        public :
             int compare(T data1, T data2){
            
                if(data1< data2)
                          return -1;
                 if(data1>data2)
                          return 1;
                 return 0;                        
                
                }
       };


Wyczytałam że metoda virtualna, powoduje że klasa jest abstrakcyjna. Wywołuję to w ten sposób:

DLRing<int> ring;
cout<<"Dodajemy\n";
 ring.addAtEnd(2);
 ring.addAtEnd(1);
 
ring.print();

AscendingOrderComparator<int> comparator;

 ring.sort(comparator);
ring.print();

Niestety kodu w obecnej postaci nie da się skompilować - jest wyrzucany błąd:
// cannot allocate an object of type `Comparator<int>' because the following virtual functions are abstract: Comparator<T>::compare(T, T) [with T = int]
//

Jeśli w klasie Comparator dodam ciało funkcji (dalej zostawiając ją wirtualną) i to program się uruchamia, ale sortuje według funkcji z klasy Comparator, a nie dziedziczącej po niej AscendingOrderComparator, mimo że obiekt klasy AscendingOrderComparator jest w wywołaniu przekazywany do funkcji sort.

Bardzo liczę na Waszą pomoc

0

Chyba zapomniałam postawić pytania :) W jaki sposób można zrobić coś takiego, żeby w metodzie sort były wykonywane funkcje z klasy AscendingOrderComparator (lub dowolnej klasy która dziedziczy po Comparator) a nie z klasy rodzica.

0

kompilator wypluwa ci taki błąd ponieważ próbujesz utworzyć obiekt klasy, która posiada niepełną definicję. Klasa abstrakcyjna w c++ to taka, która posiada przynajmniej jedną metodę czysto wirtualną czyli taką, którą na poziomie klasy abstrakcyjnej nie posiada własnej definicji. Jest ona dopiero definiowana dalej w hierarchii. Natomiast metoda może być również wirtualna i posiadać definicje - w tej sytuacji gdy w klasie potomnej nie zrobisz jej redefinicji będzie wywoływana ta z klasy bazowej.

0

poza tym

virtual typ metoda() = 0; 

a nie

typ virtual metoda() = 0;
0

Dzięki za odpowiedź, ale przyznam że nic mi nie rozjaśniła. Nie tworzę przecież obiektu klasy abstrakcyjnej Comparator, tylko klasy dziedziczącej po niej - AscendingOrderComparator. W metodzie sort jako parametr pobieram klasę Comparator, bo chcę korzystać z poliformizu. W jaki sposób powinnam zatem przepisać mój kod, żeby to zadziałało z poliformizmem?

0
#include <iostream>
#include <string>
#include <cxxabi.h>

using namespace std;

template<class T>
    inline string className(const T &obj) {
        return string(abi::__cxa_demangle(typeid(obj).name(), 0, 0, 0));
    }

class Base {
    public:
        virtual void p() = 0;
};

class A : public Base {
    public:
        void p(){}
};

//void foo(Base b) { cout << className(b); }
void foo2(Base &b) { cout << className(b); }

int main()
{
    A a;
    A *a2 = new A;
    foo2(*a2);
    cout << "\n";
    foo2(*dynamic_cast<Base*>(&a));
    delete a2;
    return 0;
}

teraz widzisz? Polimorfizm "nie działa" przy przekazywaniu przez wartość.

0

Tego dynamic_cast miało tam nie być. Zapomniałem usunąć :)

0

Czyli wystarczyło przekazywać przez referencję i zadziałało - Dzięki za pomoc! :)

0

albo przez wskaźnik. Ogólnie rzecz biorąc funkcje wirtualne wymagają użycia referencji lub wskaźnika :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1