Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Klasa pochodna i zapis wskaźnika

Ostatnio zmodyfikowano 2022-02-06 21:20
Autor Wiadomość
Nekronomik
Temat założony przez niniejszego użytkownika
» 2022-02-05 11:22:30
Na klasie Obiekty mam napisaną listę i drzewko czwórkowe. Teraz sztywno muszę się trzymać klasy abstrakcyjnej i tworzyć nią obiekty:
Obiekty * nowy_1 = new AA
Nie mogę tak zrobić:
AA * nowy_1 = new AA;
P-179267
DejaVu
» 2022-02-05 11:58:10
Jeżeli tworzysz kontenery danych, to proponowałbym Ci zrobić po prostu szablony zamiast pchać się w trudno utrzymywalne dziedziczenie. Jak zaimplementujesz sobie drzewo czwórkowe jako kontener to wszystkie problemy Ci znikną. Ponadto będziesz miał re-używalny (oraz przetestowany) kontener do każdego innego problemu. Finalny kod będzie też prostszy w zrozumieniu.

Czyli zamiast rzeźbić dziedziczenia możesz mieć po prostu:
C/C++
template < class T >
class QuadTree
{
   
}
;

Wówczas nie masz potrzeby robienia jakichkolwiek rzutowań. Masz od razu interfejs taki, jaki potrzebujesz. Kod jest szybszy, bo nie musisz 'wyłuskiwać' odpowiedniego typu obiektu. Nie komplikujesz kodu poprzez tworzenie sztucznych interfejsów dla obiektów, które chcesz wpychać do drzewa.

Listy nie musisz własnej implementować. Masz std::list<T> dostępne w standardowym C++.

/edit:
Jeżeli Twoim celem jest zaimplementowanie QuadTree to masz ciekawe zajęcie. Jeżeli chcesz po prostu mieć QuadTree to możesz spróbować znaleźć gotową implementację i skupić się na rozwiązywaniu Twojego właściwego problemu.

Pierwszy lepszy strzał w Google: https://github.com/pvigier/Quadtree (licencja MIT, więc możesz używać do czego chcesz).

Nie sugeruję, że od razu masz użyć biblioteki 3rd-party, ale może ten wywód będzie dla Ciebie jakimś źródłem inspiracji :)

/edit:
Publiczne API w tym kontenerze do którego podesłałem linka wygląda prosto:
C/C++
template < typename T, typename GetBox, typename Equal = std::equal_to < T >, typename Float = float >
class Quadtree
{
public:
   
Quadtree( const Box < Float > & box, const GetBox & getBox = GetBox(), const Equal & equal = Equal() );
   
   
void add( const T & value );
   
   
void remove( const T & value );
   
   
std::vector < T > query( const Box < Float > & box ) const;
   
   
std::vector < std::pair < T, T >> findAllIntersections() const;
}
Pytanie brzmi: czy za jego pomocą jesteś w stanie uzyskać to czego potrzebujesz (zakładam, że tak):
P-179268
Nekronomik
Temat założony przez niniejszego użytkownika
» 2022-02-05 12:26:27
Mam osobny kontener do listy i do drzewka czwórkowego. To już wszystko działa, w najbardziej pesymistycznej sytuacji np ok 3000 obiektów obok siebie przy sprawdzaniu kolizji daje mi stałe 60 fps. Obiekty już się poruszają, strzelają do siebie, niszcza się, reagują na siebie. Problem pojawił sie gdy stworzyłem obiekt modułowy który składa się z kilku obiektów . Dlatego teraz kombinuję z tym aby obiekt miał w pełni kontrolę nad modułami.
P-179269
DejaVu
» 2022-02-05 12:35:57
Jeżeli problem nie dotyka QuadTree/List (czyli kontenerów), ale użycia obiektu wewnątrz niego to możesz rozważyć np. zdefiniowanie rozbudowanego interfejsu bazowego:
C/C++
class Object
{
   
virtual ~Object() { }
   
   
virtual Module1 * getModule1() { return nullptr; }
   
virtual Module2 * getModule2() { return nullptr; }
   
virtual Module3 * getModule3() { return nullptr; }
}

class Tank
    : public Object
{
   
   
Module1 * getModule1() override { return m_module1; }
   
Module2 * getModule2() override { return m_module2; }
}
;

class Jeep
    : public Object
{
   
   
Module1 * getModule1() override { return m_module1; }
}
;

Wówczas masz łatwe API bazowe za pomocą którego możesz wyciągać dowolne informacje o modułach już we właściwym typie. Wada: musisz rozszerzać interfejs bazowy, aby zawierał wszystkie typy/moduły. Zaleta: mega proste w użyciu/utrzymaniu/rozwoju.
P-179270
Nekronomik
Temat założony przez niniejszego użytkownika
» 2022-02-05 15:24:25
Przebudowa kodu na te chwilę była by z byt bolesna. Teoretycznie znalazłem sposób.
Tworzę metodę wirtualną w klasie abstrakcyjnej np:
virtual Moduly( Obiekty * m1, Obiekty * m2, Obiekty * m3, Obiekty * m4, Obiekty * m5 ) = 0;
 i w klasie pochodnej np BB pisze tak;
C/C++
virtual Moduly( Obiekty * m1, Obiekty * m2, Obiekty * m3, Obiekty * m4, Obiekty * m5 )
{
   
zapisz_1 = m1;
   
zapisz_2 = m2;
}
Minus tego taki że w każdej klasie pochodnej musze tą metodę wirtualną dodać, no i sam zapis jest średni.

Czyli obecnie na te chwilę nie ma prostego sposobu na przypisanie wskaźnika do zapisz_1 który znajduje się tylko w klasie pochodnej BB a wszystkie obiekty tworzone są za pomocą klasy abstrakcyjnej

Obiekty * nowy_3 = new BB;
nowy_3->zapisz_1 = nowy_1;   <---bo zapisz_1 należy do klasy pochodnej BB ale nie do klasy abstrakcyjnej Obiekty więc nie mam do niego dostępu a musze mieć ^
P-179271
DejaVu
» 2022-02-05 16:01:41
No właśnie opisałem Ci rozwiązanie bezbolesne... dodajesz metodę wirtualną dajZapisz1() do klasy bazowej, która zwraca nullptr. W klasie pochodnej 'BB' tworzysz sobie zmienną m_zapisz1 i przeciążasz metodę wirtualną dajZapisz1(), aby zwracała m_zapisz1. Problem masz rozwiązany, bo nie musisz 'wszystkiego' rozszerzać. Dane są trzymane tylko w obiekcie pochodnym. Z obiektu typu bazowego możesz uzyskać wskaźnik do obiektu za pośrednictwem dajZapisz1(), którego właścicielem może (ale nie musi być) Twój obiekt typu 'BB'.
P-179272
Nekronomik
Temat założony przez niniejszego użytkownika
» 2022-02-05 23:55:19
DejaVu rozumiem zamysł ale nie widzę kodu, nie mam pojęcia jak go użyć/napisać mimo że dałeś kawałek przykładu z opisem.
P-179273
Nekronomik
Temat założony przez niniejszego użytkownika
» 2022-02-06 17:36:19
No tak... na początku myślałem że podałeś taki kod "pokazowy" a jednak nie. Kompilator mi pluje błędami o "override" bo nie wie co to jest.
P-179274
1 « 2 » 3
Poprzednia strona Strona 2 z 3 Następna strona