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

OOP C++ - no matching function call [POLIMORFIZM]

Object Storage Arubacloud
+1 głos
346 wizyt
pytanie zadane 27 grudnia 2017 w C i C++ przez MAGNET Nowicjusz (160 p.)
edycja 27 grudnia 2017 przez MAGNET
Witam,

od jakiegoś czasu uczę się OOP. Jest to dla mnie całkiem nowy temat (wcześniej 100% proceduralnie) i nie czuję się jeszcze do końca swobodnie w tym środowisku, z czego wynikają pewne problemy...takie jak ten, z którym dzisiaj przychodzę.

Piszę prosty plugin, który miałby symulować księgarnię. Do tej pory szło w miarę gładko, jednak kiedy chciałem zaimplementować dodawanie nowej książki przy pomocy polimorfizmu, natrafiam na błąd, którego nie potrafię naprawić

error: no matching function call to 'Ksiazka_Sportowa::Ksiazka_Sportowa()'

Wydaje się, że istnieją rozbieżności w przekazywanych parametrach, jednak próbowałem je korygować na rozmaite sposoby - bezskutecznie.

Na chwilę obecną logika skryptu wygląda następująco: po odpaleniu ukazuje się menu z opcjami - obecnie dostępne jest jedynie dodanie nowej książki. Po wybraniu tej opcji ukazuje się kolejne menu, w którym wybieramy jaki GATUNEK książki chcemy dodać. Po wybraniu np. sportowej przy pomocy polimorfizmu kierujemy się do odpowiedniego formularza w celu uzupełnienia danych. Na końcu całość trafia do odpowiedniego vectora (jeszcze nie dodane).

https://pastebin.com/RKBD5YCR

WERSJA PO POPRAWKACH: https://github.com/MAGNET1/avl

błąd dotyczy linijki nr 31 i 37

 

Mój zestaw pytań:

1. Czego dokładnie dotyczy ten błąd i jak najlepiej sobie z nim radzić

2. Czy polimorfizm został użyty w tym przypadku poprawnie - może zasadnym byłoby użycie innego rozwiązania?

3. Czy w kodzie dostrzegasz jeszcze jakieś nieścisłości? Coś, co możnaby napisać lepiej? [tak jak mówiłem, paradygmat obiektowy nie jest mi jeszcze w pełni przyjazny, dlatego z chęcią przyjmę każdą radę dotyczącą tego, jak należy pisać]

4. Zastanawia mnie, jaki jest lepszy sposób na napisanie "menu" - wydaje mi się, że można to zrobić lepiej, jednak nie wiem jak

 

Jestem pewien, że na tym forum aktywna jest masa doświadczonych programistów, która pomoże rozwiązać ten problem :)

Z góry dziękuję i pozdrawiam!

1 odpowiedź

+1 głos
odpowiedź 27 grudnia 2017 przez Patrycjerz Mędrzec (192,320 p.)
wybrane 30 grudnia 2017 przez MAGNET
 
Najlepsza

1. Wywołujesz konstruktory domyślne, które nie istnieją. W twoim przypadku zostaje wywołanie konstruktorów, które zdefiniowałeś.

2. Patrz punkt 3.

3. W ogóle ten kod jest niepoprawnie zbudowany.

3.1. W konstruktorach nie powinno się znajdować wprowadzanie danych z konsoli. Nie jest to reprezentatywne rozwiązanie. Sam konstruktor nie niesie za sobą informacji, że wywołuje on jakiś interfejs użytkownika. Od tego powinna być oddzielna metoda.

3.2. Tworzenie oddzielnych wektorów dla każdego typu książek mija się z uniwersalnością kodu, którą przecież oferuje polimorfizm. Kontener powinien być jeden z zawartymi wskaźnikami na klasę bazową. Interfejs implementowany zaś przez klasy pochodne powinien pokrywać wszelakie operacje potrzebne każdemu typowi książek.

3.3. Rekurencyjne wywoływanie funkcji main to proszenie się o przepełnienie stosu! Po to zostały stworzone warunki i pętle, abyś mógł przekierować sterowanie znowu do kodu menu.

3.4. Klasa Menu_NowaKsiazka nie ma racji bytu. Niech dziedziczy ona z klasy Menu, przykrywając metodę wirtualną PobierzOpcje, lub niech Menu ma dwie metody dla dwóch różnych sposobów wprowadzania opcji.

4.

Zastanawia mnie, jaki jest lepszy sposób na napisanie "menu"

 Co masz na myśli pisząc "menu"? Klasę Menu czy funkcję main?

komentarz 27 grudnia 2017 przez MAGNET Nowicjusz (160 p.)

Co masz na myśli pisząc "menu"? Klasę Menu czy funkcję main?

Myślę, że jedno i drugie. Jak to powinno wyglądać zarówno w klasie jak i w funkcji main 

1
komentarz 27 grudnia 2017 przez Patrycjerz Mędrzec (192,320 p.)
Tak jak mówiłem, konstruktory nie powinny odpowiadać za interfejs użytkownika. No i rekurencyjne wywoływanie funkcji main powinno zniknąć. Tak poza tym nie wygląda to źle. Osobiście obudowałbym menu z maina w jakąś klasę, ale nie jest to konieczne w tak prostym kodzie. Masz o wiele poważniejsze problemy projektowe, które należy na początku rozwiązać, to możesz sobie zostawić na deser.
komentarz 27 grudnia 2017 przez MAGNET Nowicjusz (160 p.)
Bardzo dziękuję za kompleksowe wyjaśnienia. Doprowadzę kod do porządku i zapytam się jeszcze o jego poprawność
komentarz 27 grudnia 2017 przez MAGNET Nowicjusz (160 p.)
Czy mógłbyś szczegółowiej wyjaśnić mi, jak miałaby wyglądać implementacja punktu 3.2? Skoro tworzę obiekty, które dziedziczą po klasie bazowej, jak mogę stworzyć wektor obiektów "książka"? Domyślam się, że wymaga to przebudowania kodu od podstaw, ale nie do końca wyobrażam sobie, jak miałoby to wyglądać, skoro w klasie bazowej nie ma zawartych informacji, które posiadają dziedziczące po niej klasy?
1
komentarz 27 grudnia 2017 przez Patrycjerz Mędrzec (192,320 p.)
Rzeczywiście, masz wtedy dostęp jedynie do pól i metod klasy bazowej, ale zauważ, że metody wirtualne są przysłaniane, co oznacza, że mogą posiadać odpowiedniki z klas pochodnych, które korzystają z danych niedostępnych w klasie bazowej. W wielkim skrócie: interfejs wszystkich klas musi być taki sam, lecz implementacja może być dowolna.
komentarz 27 grudnia 2017 przez MAGNET Nowicjusz (160 p.)
https://github.com/MAGNET1/avl

Jak to wygląda teraz? :D
1
komentarz 27 grudnia 2017 przez Patrycjerz Mędrzec (192,320 p.)

Wygląda to o wiele lepiej, tylko mam kilka zastrzeżeń:

  1. Tworząc obiekty za pomocą metody StworzKsiazke powodujesz wycieki pamięci. Wektor nie wywołuje operatora delete na adresach, gdyż jego zadaniem jest jedynie zarządzanie grupą wskaźników, nie pamięcią, na którą wskazują. Z tego też powodu musisz albo wywoływać delete ręcznie, albo użyć smart pointerów, w tym przypadku std::unique_ptr. W skrócie zamiast wektora wskaźników tworzysz wektor smart pointerów, które przechowują wskaźniki.
  2. Klasa Factory nie ma racji bytu. Po pierwsze jej nazwa nie jest adekwatna do zawartości, po drugie jej metody czysto-wirtualne nie są potrzebne, aby korzystać z zalet polimorfizmu, wystarczy, że dodasz słówko virtual do metod publicznych klasy Ksiazka, po trzecie metodę StworzKsiazke można bez przeszkód przenieść do klasy Ksiazka.
  3. vKsiazka[vKsiazka.size()-1] to inaczej vKsiazka.back(). Iteracja x w casie trzecim nie ma najmniejszego sensu. Przecież masz vKsiazka.size().
komentarz 30 grudnia 2017 przez MAGNET Nowicjusz (160 p.)
Super! Bardzo dziękuję za udzieloną pomoc. Jeśli po drodze trafię na jakiś problem założę oddzielny temat

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.)
0 głosów
1 odpowiedź 287 wizyt
pytanie zadane 21 października 2016 w C i C++ przez PaulW Początkujący (470 p.)
0 głosów
2 odpowiedzi 6,723 wizyt
pytanie zadane 25 lipca 2016 w C i C++ przez MatrixBMW Początkujący (360 p.)

92,579 zapytań

141,432 odpowiedzi

319,657 komentarzy

61,963 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!

...