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

question-closed Tworzenie obiektu na podstawie wsk polimorficznego? Jak okreslic typ?

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
0 głosów
989 wizyt
pytanie zadane 25 września 2018 w C i C++ przez Poczprogramista123 Bywalec (2,900 p.)
zamknięte 26 września 2018 przez Poczprogramista123
Przedstawie problem. Mam funkcje ktora dostaje wskaznik polimorficzny. I teraz chce uzyskac informacje jakiego typu(czyli jakiej klasy pochodnej) jest obiekt na ktory ten wskaznik wskazuje. Dokladniej chce stworzyc nowy obiekt tego samego typu ale nie znam tego typu.

Dodam ze wskaznik polimorficzny jest z klasy abstrakcyjnej wiec nie mam jak stworzyc obiektu. Cos probowalem z typeid piszac takie cos.

void cos(Postac *wsk)

Postac* nowyobiekty=new typeid(*wsk);

Z gory dzieki.
komentarz zamknięcia: Dzieki za odpowiedzi. Problem rozwiazany
1
komentarz 26 września 2018 przez mokrowski Mędrzec (158,660 p.)
Powinno paść pytanie raczej nie "jak" a "dlaczego". Tak więc dlaczego masz konstrukcję w której najprawdopodobniej chcesz łamać regułę Liskov?
komentarz 26 września 2018 przez Poczprogramista123 Bywalec (2,900 p.)
Metoda prob i bledow. Dzieki za nowy termin
komentarz 26 września 2018 przez mokrowski Mędrzec (158,660 p.)
Detekcja typu poprzez próbę rzutowania lub sprawdzanie "znacznika typu", świadczy najczęściej (rząd ~90%) o nieprzemyślanym projekcie i łamaniu jednej z reguł S.O.L.I.D. Oczywiście żadne reguły "nie są świętością za które dają medale", tak jak programowanie nie jest religią :) Ale warto wiedzieć jakie problemy sobie generujesz. RTTI (Run Time Type Information), bywa zabroniony w niektórych projektach ze względu na narzut związany z jego obsługą. Poza tym informacje zwracane przez typeid, są nieprzenośne pomiędzy kompilatorami (każdy może inaczej nazywać dany typ). Oczywiście że sobie z tym radzisz... tylko ten koszt...

Sam dynamic_cast, bywa toksyczny: https://en.cppreference.com/w/cpp/language/dynamic_cast Jeśli się da (i koniecznie trzeba) rzutować w dół drzewa dziedziczenia, to lepiej ograniczać się do static_cast. W wielu przypadkach wystarcza do poprawnej detekcji a nie jest kosztowny w trybie wykonania (runtime).

W uzupełnieniu, zerknij jeszcze do pojęć: https://en.wikipedia.org/wiki/Double_dispatch oraz https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

Tak.. wiem że nie odpowiedziałem "jak to zrobić" a co o tym myślę... inni odpowiedzieli a mnie poniosło :) Wybacz...
komentarz 26 września 2018 przez Poczprogramista123 Bywalec (2,900 p.)
Dzieki. I racja wystarczylo spojrzec na problem z drugiej strony. Czasem o tym sie zapomina ze nasz pierwszy pomysl moze nie jest najlepszy na swiecie i warto przemysles jeszcze inne wariany.

5 odpowiedzi

+1 głos
odpowiedź 26 września 2018 przez Piotr Batko Stary wyjadacz (13,210 p.)
+1 głos
odpowiedź 26 września 2018 przez monika90 Pasjonat (22,940 p.)
edycja 26 września 2018 przez monika90

Odpowiedź znajdziesz w FAQ https://isocpp.org/wiki/faq/virtual-functions sekcja: What is a “virtual constructor”?

Oczywiście, zamiast Postac* zwracaj std::unique_ptr<Postac>

+1 głos
odpowiedź 26 września 2018 przez Ehlert Ekspert (215,010 p.)
  1. Stwórz w klasie bazowej wskaźnika metodę getType zwracającą stałą wartość per typ dziedziczący lub enum class. Dzięki temu unikniesz castow. 
  2. Przerób kod aby uniknąć tej sytuacji. Solid się sypie. Po to masz gdzieś wskaźnik polimorficzny żeby się przejmować się co pod nim jest. 
komentarz 26 września 2018 przez criss Mędrzec (172,570 p.)

Dzięki temu unikniesz castow. 

Precyzując: unikniemy dynamic_cast (RTTI), ale static_cast będzie wciąż konieczny jeśli chcemy, żeby kompilator też wiedział

0 głosów
odpowiedź 25 września 2018 przez adamus Użytkownik (860 p.)

 Example 23.5. Zobacz w tym przykladzie.

0 głosów
odpowiedź 26 września 2018 przez criss Mędrzec (172,570 p.)

Kombinacja dynamic_cast oraz switch..case wystarczy.

komentarz 26 września 2018 przez Ehlert Ekspert (215,010 p.)

To się sprawdzi ale czy z logicznego punktu widzenia to ma sens? smiley

komentarz 26 września 2018 przez criss Mędrzec (172,570 p.)

Cytat z twjej odpowiedzi: 

  1. Stwórz w klasie bazowej wskaźnika metodę getType zwracającą stałą wartość per typ dziedziczący lub enum class. Dzięki temu unikniesz castow. 

Teoretycznie oznacza to, że coś poszło nie tak z designem (z każdą dodaną klasą pochodną musisz dodwać nową wartość enum, co troche psuje idee polimofizmu), ale z doświadczenia wiem, że czasem inaczej się nie da albo jest znacznie prościej. No i z wydajnościowego punktu widzenia jest lepsze niż dynamic_cast. Jako performance fan jestem za twoim rozwiązaniem bardziej niż za moim, ale o ile to możliwe, powinno się unikać i tego i tego.

komentarz 26 września 2018 przez Ehlert Ekspert (215,010 p.)

W pełni się zgadzam. Najlepiej wgl nie sprawdzać typów. If you know what I mean devil

komentarz 26 września 2018 przez criss Mędrzec (172,570 p.)
Po ostatnim zdaniu mam wątpliwości czy i know what u mean XD

Podobne pytania

+1 głos
0 odpowiedzi 292 wizyt
+1 głos
1 odpowiedź 336 wizyt
pytanie zadane 8 października 2020 w SQL, bazy danych przez Mateusz Kita Początkujący (380 p.)
+1 głos
1 odpowiedź 172 wizyt
pytanie zadane 14 listopada 2016 w C i C++ przez Avernis Nałogowiec (27,400 p.)

93,440 zapytań

142,431 odpowiedzi

322,679 komentarzy

62,802 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

...