• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dziedziczenie oraz polimorfizm - problem z zadaniem.

Object Storage Arubacloud
0 głosów
501 wizyt
pytanie zadane 1 sierpnia 2015 w C i C++ przez John Doe Obywatel (1,720 p.)

Witam odwiedzających.

Ostatnimi czasy, uczę się C++ z książki Allaina Alexa (C++. Przewodnik dla początkujących) i utknąłem na następującym zadaniu:

Zaimplementuj funkcję sortuj pobierającą wektor wskaźników do klasy interfejsowej „Porownywalne”, która definiuje metodę „porownaj(Porownywalne& inny)” i zwraca 0, kiedy obiekty są takie same, 1, kiedy porównywany obiekt jest większy od obiektu „inny”, oraz -1, gdy obiekt jest mniejszy od obiektu „inny”. Napisz klasę implementującą ten interfejs, utwórz kilka jej instancji i posortuj je. Jeśli nie wiesz, jaką klasę utworzyć, spróbuj zmierzyć się z klasą „TabelaWynikow”, która zawiera nazwy oraz punktację i sortuje dane w taki sposób, że najwyższe punktacje znajdują się na początku. Jeśli dwie punktacje są takie same, sortowanie powinno odbywać się według nazw.

Nie mam pojęcia jak się za nie zabrać.

Czy ktokolwiek mógłby mi pomóc w rozwiązaniu tego zadania?

Jakiekolwiek wskazówki, kody/własne implementacje byłyby mile widziane.

Pozdrawiam :)

1 odpowiedź

+1 głos
odpowiedź 1 sierpnia 2015 przez adrian17 Ekspert (344,860 p.)
Boczna notka: czegoś takiego normalnie się unika w C++'ie, bo wymaga rzutowania w dół. Ogólnie porównywania raczej nie łączy się z polimorfizmem; jeśli próbujesz porównać Kwadrat i Kółko, to prawdopodobnie coś jest nie tak w samym designie programu. (no i w C++ porównywanie typowo implementuje się przez przeładowanie operator<)

Natomiast jest to całkowicie normalne w C#, gdzie istnieje interfejs IComparable z metodą CompareTo, działające właściwie dokładnie tak, jak opisałeś.
komentarz 1 sierpnia 2015 przez John Doe Obywatel (1,720 p.)

Jesteś pewien, że wymagane jest tu rzutowanie w dół?

Usiadłem na „chwilę” przy kompliatorze i wymyśliłem coś takiego:

#include <iostream>
#include <vector>

using namespace std;

//---------------------------------------------------------
class Porownywalne
{
public:
    int porownaj(Porownywalne& inny)
    {
        if(this->punkty == inny.punkty) return 0;
        if(this->punkty < inny.punkty) return -1;
        if(this->punkty > inny.punkty) return 1;
    }
    virtual string getName() = 0; // funkcja testowa do sprawdzenia czy nastapila podmiana
protected:
    string nazwa;
    int punkty;
};

class TabelaWynikow: public Porownywalne
{
public:
    TabelaWynikow(string n = "John", int p = 0) { nazwa = n; punkty = p; }
    string getName() { return nazwa; }
};
//---------------------------------------------------------
void sortuj(vector <Porownywalne*> &vRef)
{
    if(vRef[0]->porownaj(*vRef[1]) > 0)
        swap(vRef[0], vRef[1]);
}
//---------------------------------------------------------
int main()
{
    TabelaWynikow a("Eric", 20);
    TabelaWynikow b("Robert", 5);

    vector <Porownywalne*> x;

    x.push_back(&a);
    x.push_back(&b);

    sortuj(x);

    cout << x[0]->getName();
}

Funkcja sortuj do rozbudowy. Ale czy to w ogóle jest poprawnie zrobione? Czy o to chodziło w zadaniu? 

komentarz 1 sierpnia 2015 przez adrian17 Ekspert (344,860 p.)
Nie. W zadaniu interfejs "porównywalne" ma dać metodą porownaj(), a klasy po niej dziedziczące mają ją zaimplementować. No i zazwyczaj definicja interfejsu mówi, że nie powinien mieć on niczego poza metodami abstrakcyjnymi.
komentarz 1 sierpnia 2015 przez John Doe Obywatel (1,720 p.)

Czyli wówczas, ta metoda porownaj(Porownywalne& inny) nie będzie możliwa do wykonania bez rzutowania w dół, dobrze rozumiem?

komentarz 1 sierpnia 2015 przez adrian17 Ekspert (344,860 p.)
Tak, ponieważ argument ma typ Porownywalne&, a właściwe dane związane z obiektem są w klasie TabelaWynikow, więc trzeba go przerzutować na TabelaWynikow&.
komentarz 1 sierpnia 2015 przez John Doe Obywatel (1,720 p.)
Przepraszam, ale czy mógłbyś mi to przedstawić w postaci kodu? :)
komentarz 2 sierpnia 2015 przez adrian17 Ekspert (344,860 p.)
edycja 2 sierpnia 2015 przez adrian17

(disclaimer: w praktyce naprawdę nie powinno się tego używać do porównywania; ale ogólnie jest to typowy przykład interfejsu w C++.) Dla uproszczenia moja funkcja porównaj po prostu zwraca bool (a nie -1/0/1).

struct IPorownywalny {
	virtual bool porownaj(IPorownywalny& inny) = 0;

	virtual ~IPorownywalny(){};
};

struct Klasa : public IPorownywalny {
	int liczba;

	bool porownaj(IPorownywalny& inny) {
		Klasa &inny_klasa = dynamic_cast<Klasa&>(inny);
		return liczba < inny_klasa.liczba;
	};
};

 

komentarz 2 sierpnia 2015 przez John Doe Obywatel (1,720 p.)

Może to głupie pytanie, ale ja tego nie widzę - gdzie obiekt inny otrzymuje wartość, jeśli po takim rzutowaniu można ją wywołać (inny_klasa.liczba)?

komentarz 2 sierpnia 2015 przez adrian17 Ekspert (344,860 p.)

...nie rozumiem pytania. Dla pewności, tą funkcję się używa tak:

	Klasa obiekt1, obiekt2;
	obiekt1.liczba = 10;
	obiekt2.liczba = 20;
	bool wiekszy = obiekt1.porownaj(obiekt2);

 

komentarz 2 sierpnia 2015 przez John Doe Obywatel (1,720 p.)
Ach! Już rozumiem, serdecznie dziękuję :D

Podobne pytania

0 głosów
4 odpowiedzi 6,049 wizyt
pytanie zadane 30 stycznia 2016 w C i C++ przez Mateo500 Nowicjusz (150 p.)
+1 głos
1 odpowiedź 288 wizyt
pytanie zadane 3 lutego 2016 w C i C++ przez Ziuziek Mądrala (5,140 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...