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

Wydajność: zmienne statyczne dla każdej podklasy czy wskaźniki

Ostatnio zmodyfikowano 2017-08-19 21:00
Autor Wiadomość
latajacaryba
Temat założony przez niniejszego użytkownika
» 2017-08-18 23:01:58
@mokrowski
Ja rozumiem działanie polimorfizmu. Zauważ tylko, że klasa "drzwi" dziedziczy po klasie pole, więc jeśli mam referencje/wskaźnik do zwykłego pola oraz do drzwi i gracz chce wejść w interakcję z drzwiami, to muszę wywołać metodę:
C/C++
PolePtr->Interakcja();
A TO oznacza, że w klasie Pole musi być metoda wirtualna "interakcja". To może jeszcze działać, ale co, jeśli mam w klasie "Drzwi" stan drzwi -
bool SaOtwarte
? Z poziomu wskaźnika do klasy Pole nie moge się do tego dostać...
C/C++
PolePtr = & Drzwi;
bool CzyDrzwiSaOtwarte = PolePtr->SaOtwarte; // blad, odwolanie sie do elementu niezdefiniowanego w klasie Pole

Więc jak mogę odwoływać się do składników klasy pochodnej, mając wskaźnik klasy podstawowej? Jak to załatwić?
P-164093
jankowalski25
» 2017-08-18 23:45:18
Przez
dynamic_cast
.
P-164095
latajacaryba
Temat założony przez niniejszego użytkownika
» 2017-08-19 00:21:18
Też o tym myślałem, jednak nie zawsze wiadomo, czy to są drzwi, fontanna lecznicza czy co innego. Mam taki pomysł:
InterakcyjnePole dziedziczy po Pole. Klasa pole ma metode bool CzyInterakcyjne. Jeśli zwróci true, robię konwersję w dół (Pole na InterakcyjnePole) i wywołuje Interakcja :)
Dzięki
P-164097
mokrowski
» 2017-08-19 01:33:51
@latajacaryba, to dobrze że rozumiesz polimorfizm. Stąd będziesz wiedział że wystarczy zaimplementować metodę wirtualną zwracającą znacznik "kim jest klasa" i na tej podstawie zróżnicujesz wywołania lub zastosować inną metodę która będzie działała podobnie...
Tak czy siak łamiesz taką detekcją regułę Liskov https://pl.wikipedia.org/wiki/Zasada_podstawienia_Liskov

Nie sądzisz że Drzwi nie są rodzajem Pola? Oględnie mówiąc mają inne rodzaje interakcji więc inne interfejsy.
C/C++
#include <iostream>
#include <vector>

class Drzwi;
class Krzaczor;

struct Pole {
    virtual int kto() const = 0;
    virtual void interakcja( Pole * ) = 0;
    virtual void interakcja( Drzwi * ) = 0;
    virtual void interakcja( Krzaczor * ) = 0;
    virtual ~Pole() { }
};

struct Drzwi
    : Pole
{
    Drzwi()
        : otwarte
    { false } { }
   
    int kto() const override {
        return 1;
    }
   
    void interakcja( Drzwi * ) override {
        std::cout << "Drzwi\n";
    }
   
    void interakcja( Krzaczor * ) override {
    }
   
    void interakcja( Pole * pole ) override {
        pole->interakcja( this );
    }
   
    bool czyOtwarte() const {
        return otwarte;
    }
    void otwarcie() {
        otwarte = true;
    }
    void zamkniecie() {
        otwarte = false;
    }
private:
    bool otwarte;
};

struct Krzaczor
    : Pole
{
    int kto() const override {
        return 2;
    }
    void interakcja( Krzaczor * ) override {
        std::cout << "Krzaczor\n";
    }
   
    void interakcja( Drzwi * ) override {
    }
   
    void interakcja( Pole * pole ) override {
        pole->interakcja( this );
    }
};

struct Akcja {
    void akcjaPrzezId( Pole * pole ) {
        if( pole->kto() == 1 ) {
            std::cout << "Drzwi...\n";
        } else if( pole->kto() == 2 ) {
            std::cout << "Krzaczor...\n";
        }
    }
    virtual void akcja( Drzwi * drzwi ) {
        std::cout << "Drzwi\n";
    }
    virtual void akcja( Krzaczor * krzaczor ) {
        std::cout << "Krzaczor\n";
    }
};

int main() {
    Akcja * a = new Akcja();
    std::vector < Pole *> rzeczy;
   
    for( auto i = 0U; i < 5; ++i ) {
        rzeczy.push_back( new Krzaczor() );
    }
    for( auto i = 0U; i < 3; ++i ) {
        rzeczy.push_back( new Drzwi() );
    }
    std::cout << "Przez ID\n";
    for( auto & rzecz: rzeczy ) {
        a->akcjaPrzezId( rzecz );
    }
   
    std::cout << "Przez polimorfizm \n";
    for( auto & rzecz: rzeczy ) {
        rzecz->interakcja( rzecz );
    }
   
    for( auto & p: rzeczy ) {
        delete p;
    }
    delete a;
}
P-164099
latajacaryba
Temat założony przez niniejszego użytkownika
» 2017-08-19 02:25:40
No właśnie podświadomie wiem, ze coś jest nie tak, że musi być metoda mówiąca, czym jest obiekt ją wywołujący.
Drzwi zdecydowałem się umieścić jako pochodną klasy pole, gdyż wszystkie pola/struktury chce trzymać w dwuwymiarowej tablicy wskaźników do obiektów pole.
Nie mam pojęcia jak to inaczej załatwić :/
Chcę, by mając wskaźnik program sprawdzał, czy z polem da się wykonać interakcję. Jeśli tak, to ją wykonuje.
P-164100
michal11
» 2017-08-19 09:50:42
Zrób kilka tablic i niech każdy obiekt w grze rejestruje się do tego co go interesuje ( rendering, kolizje, fizyka itp.), dodatkowo możesz poczytać o delegatach (tak to się chyba tłumaczy na polski) i o wzorcu obserwator.
P-164101
latajacaryba
Temat założony przez niniejszego użytkownika
» 2017-08-19 14:23:00
Cholera, muszę pomyśleć nad rozwiązaniem. To co mówisz byłoby całkiem Ok, tylko czasami interakcja jak otwieranie drzwi, czyli bez argumentów, innym razem leczenie gracza, czyli argument
Player &
, więc musiałbym mieć do każdego rodzaju struktury osobną tablicę... Muszę to rozwiązać tak, by łatwo było to zapisywać i wczytywać z pliku, także najwygodniejsza byłaby jedna tablica, ewentualnie kilka. Ale nie będę robił tablicy która będzie przechowywała milion elementow/wskaźników dla dwóch struktur typu fontanna życia. Ma to wyglądać jak okrojona Terraria. W założeniu. Może ktoś wpadnie na jeszcze jakiś pomysł, temat na razie zostawiam otwarty.

PS. Czytałem o delegatach, oraz wzorcu obserwator, ale tu nie znajdą raczej zastosowania, szczególnie to drugie.
P-164102
michal11
» 2017-08-19 14:50:24
Kolizja (interakcja) zawsze ma stałą, określoną liczbę argumentów, kto koliduje, z kim koliduje + ew. jakaś struktura trzymająca dane z kontekstem kolizji (np. dokładna lokacja kolizji). Możesz mieć jedna główną tablicę ktora będzie faktycznie trzymała twoje obiekty (owning pointer) i pomocnicze tablice które będą miały tylko weak pointery, tych pomocniczych nie musisz zapisywać bo każdy obiekt w konstruktorze albo jakiejś funkcji inicjującej będzie się rejestrował do odpowiedniej tablicy. Podpowiedz z delegatami i obserwatorem można wykorzystać tak, że nie rejestrujesz obiektu tylko funkcję, dzięki temu nie musisz robić specjalnego interfejsu dla klasy bazowej, wystarczy tylko aby jakaś metoda miała odpowiednią sygnaturę.
P-164103
1 2 « 3 » 4
Poprzednia strona Strona 3 z 4 Następna strona