Wpis z mikrobloga

#programowanie #cpp
Cześć, jestem początkujący w programowaniu obiektowym i natknąłem się na pewien problem, którego nie jestem w stanie rozwiązać. Mianowicie mam abstrakcyjną klasę Organizm, po której dziedziczą klasy typu 'Koala', 'Kon', 'Ptak'. Do tego chcę, aby w klasie Organizm istniała metoda nowyOrganizm, która tworzy nowy obiekt (a dokładniej wskaźnik):
Organizm *child = new Koala, new Ptak, new Kon;
No właśnie... mógłbym zaimplementować metodę w każdej z klas pochodnych z new 'typ klasy bazowej' ale chcę wykorzystać polimorfizm.

No i rodzi się pytanie, czy jest w C++ jakiś mechanizm, który pozwala zwrócić typ obiektu this? Coś na zasadzie
Organizm *child = new instanceof(this).
Ułatwiłoby mi to dość mocno życie.

P.S próbowałem z konstruktorami kopiującymi, ale wychodzi na to, że wskaznik child wskazuje na to samo miejsce w pamieci co parent, a chce, by byla na nowo alokowana pamiec.
  • 20
  • Odpowiedz
@Saly: Okej, może faktycznie jest to słabo opisane. Mam vector wskaźników na obiekty zwierząt, które dziedziczą po abstrakcyjnej klasie Organizm. W momencie gdy zajdzie kolizja między nimi chcę wywołać uniwersalną metodę dla każdego obiektu nowyOrganizm, która ma za zadanie zaalokować pamięć dla tego samego typu co obiekt, na którym wywoływana jest metoda. Potem chcę nowy wskaźnik wpisać do wektora. Coś na zasadzie metody rodzenie, które miałoby być polimorficznie wywoływane dla każdej
  • Odpowiedz
@AwizisieAkat: Dzięki, tak naprawdę o tym myślałem, ale to jest mało eleganckie, bo dla 50 klas pochodnych musiałbym napisać 50 warunków. Jeśli da się prościej i lepiej, to chciałbym wiedzieć :)
  • Odpowiedz
@j4ace: Nie da się. A przede wszystkim nie powinno się, nawet jeśli byłby jakiś pokrętny sposób, przez który byłoby to możliwe.

Nadklasa nie powinna wiedzieć nic o podklasach i nie próbować ich tworzyć/nijak ingerować w ich atrybuty/rzutować na nie/tym podobne.

Jak to zrobić poprawnie? Nadklasa organizm może posiadać metodę "nowy organizm", która może być abstrakcyjna. Podklasy przeciążają tę metodę i zwracają nowy obiekt podklasy.
  • Odpowiedz
@j4ace: dynamic_cast lub typeid z

W momencie gdy zajdzie kolizja między nimi chcę wywołać uniwersalną metodę dla każdego obiektu nowyOrganizm, która ma za zadanie zaalokować pamięć dla tego samego typu co obiekt, na którym wywoływana jest metoda. Potem chcę nowy wskaźnik wpisać do wektora.


Może czegoś nie rozumiem, ale co to ma do tej klasy? To są operacje związane z tym wektorem

Może pokaż cały kod
  • Odpowiedz
@rotflolmaomgeez: No dobra, rozumiem i tak zrobię.
@megaloxantha: Chciałem mało pisać, bo skoro każda podklasa ma mieć tę samą metodę tylko z różnym new 'Typ', to może dobrze byłoby dziedziczyć tą metodę po klasie bazowej i tylko przekazywać do niej referencję. Ale widocznie tak jest niepoprawnie ( ͡° ʖ̯ ͡°)
  • Odpowiedz
@j4ace: Nie jest niepoprawnie, to są chore nawyki z javy
Po to c++ ma multidziedziczenie i system szablonów żeby nie robić kopiuj-wklej.

A ogólnie to od czystego OO zaczyna się odchodzić właśnie z takich powodów, ta abstrakcja po prostu nie działa za dobrze.
  • Odpowiedz
@j4ace: Czytam, ale ostatecznie nie napisałeś chyba o jaką funkcjonalność ci chodzi. Rozumiem że Koala ma tworzyć nowy obiekt Koala? a Koń Konia? Do tego służy przeciążenie, overload.
  • Odpowiedz
CRTP


@lionbest: Dzięki, poczytam o tym.

@CrazyBaran: Tak, napisałem bardziej szczegółowo w drugim komentarzu. Dokładniej, szukałem rozwiązania, które omijało by przeciążanie. Chciałem użyć dziedziczenia, żeby nie overridować tej samej metody w kółko dla klas pochodnych gdzie różni się tylko 'new własny_typ'
  • Odpowiedz
A* xd = new std::remove_reference::type(); ?
Tylko generalnie musiałoby to być wywoływanie z funkcji wirtualnych danej klasy co wiąże się z tym że wyszłoby na to samo co zrobienie new A, new B, new C w danych funkcjach klasy. Jedynym wyjściem byłoby wywoływanie tego spoza klas przez normalny new decltype.
  • Odpowiedz
Ewentualnie przechowywanie lambd które tworzą dane obiekty np. w hashtablu(unordered_map) i wywoływanie po auto organizm = createOrganizm["Koala"](); albo typeid jako klucz.
Trzeba czekać na reflekcje ()
  • Odpowiedz
via Android
  • 0
@megaloxantha dzięki, przeanalizuję ten kod. Natomiast wczoraj zrobiłem jak napisał rotflolmalmgeez, napisałem czysto wirtualną metodę, którą po prostu przeciążam w klasach pochodnych. Ważne, że działa :)
  • Odpowiedz