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

Virtualny szablon metody. Czy takie cos istnieje?

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
0 głosów
653 wizyt
pytanie zadane 2 kwietnia 2019 w C i C++ przez Poczprogramista123 Bywalec (2,900 p.)

Witam. Mam taki problem, potrzeboje szablon metody w klasie i jak to przy dziedziczeniu chcialbym by ta metoda byla okreslona w klasie pochodnej czyli chce zrobic z niej metode pure virtual. I pytanie czy takie cos jest mozliwe? Bo kompilator sie czepia i szukam alternatywy.


class CGameObj
{

template<class t>
virtual void action(T *obj)=0;

}

class CItem: public CGameObj
{

template<class t>
void action(T *obj){}

}

Moim zdaniem jest to chyba jak najbardziej przydatne bo sam mechanizm dzialania na roznych typach jest dozym ulatwieniem a logiczne jest ze klasy pochodne bd miec swoje indywidualne akcje. Jak sie tak nie da to bd wdzieczny za wskazowki.

komentarz 2 kwietnia 2019 przez mokrowski Mędrzec (158,660 p.)
A potrzebny jest Ci statyczny czy dynamiczny polimorfizm? Ogólnie można uniknąć tego virtual. Tylko dokładnie trzeba wiedzieć co chcesz osiągnąć.

A bezpośrednia odpowiedź na pytanie to: Nie nie można. To 2 różne rodzaje polimorfizmu. Statyczny (szablony) i dynamiczny (virtual)
komentarz 2 kwietnia 2019 przez Poczprogramista123 Bywalec (2,900 p.)

Dzięki za odpowiedz i za to że rozjaśniłeś mi co nieco,bo nie wiedziałem że polimorfizm może być statyczny. Widze że znasz się na rzeczy, wiec przybliżę temat. Pisze gierke Mario w sfml. I mam taka hierarchie klas. 

class CRootGameObject
{

}

template<class T>
class CGameObject: public CRootGameObject
{
public:

virtual void ActOnObject(CRootGameObject *)=0;

}

/// Naprzykład

class CMario: public CGameObject<CAnimator>
{

void ActOnObject(CRootGameObject *);

}

class CItem: public CGameObject<sf::Sprite>
{
 void ActOnObject(CRootGameObject *);
}

CRootGameObject jest po to bym mogł korzystać z polimorfizmu( CRootGameObject *obj=new CMario, bo tak przecież nie moge bo jest to szablon klasy CGameObject * obj=new CMario). No i pojawia się problem związany z tworzeniem metod z odpowiednimi argumentami bo metoda ActOnObject przyjmuje za argument zrzutowany wskaznik na CRootGameObject i przez to nie mam dostepu do metod klas pochodnych czyli np do metod szablonu klasy CGameObject. Jak mogę ten problem rozwiązać? Dodam tylko że jestem totalnym samoukiem i to co tworze jest w 90% moimi własnymi pomysłami. Bd wdzięczny za wskazanie odpowiedniego schematu tworzenia gier jeśli ten jest jednak błedny.

 

 

komentarz 3 kwietnia 2019 przez mokrowski Mędrzec (158,660 p.)
No to nasuwa się pytanie po co szablon i czy wiesz że C++ wspiera dziedziczenie wielobazowe (czyli z wielu klas). Dodatkowo czy wiesz jakie są wymagania co do implementacji metod wirtualnych (gdzie jest destruktor).

A inne jeszcze, skąd pomysł na "monoteizm" całości gry... po co wspólny obiekt jak są interfejsy?
komentarz 3 kwietnia 2019 przez Poczprogramista123 Bywalec (2,900 p.)
Wiem i moze faktycznie na sile wrzucilem ten szablon. Boze jak ja kocham komentarz typu ale nie dopisales tego i tego. Tak trudno zrozumiec ze chce pokazac FRAGMENT kodu by nie przycmic tego o co mi chodzi. I ostatni twoj akapit nie jest dla mnie zrozumialy. Monoteizm? I jak to przeciez po to to jest by klasy pochodne mogly dziedziczyc atrybuty ktore sa cechami dla wszystkich obiektow gry tj. pozycja, animator(klasa odpowiedzialna za animacje obiektu itd).
komentarz 3 kwietnia 2019 przez mokrowski Mędrzec (158,660 p.)

Ja Ci zadałem pytanie czy wiesz jakie są wymagania co do dziedziczenia oraz implementacji virtual a nie czepiałem się co jest a czego nie ma. Próbujesz tworzyć pojedynczego "boga" (z małej litery) w postaci klasy CRootGameObject z którego wszyscy dziedziczą i od którego wszystko pochodzi, a nie jest tu do niczego potrzebny. Stąd w przenośni "monoteizm".

No to w takim razie nie pytam (aby nie było zarzutu o "trudno zrozumieć") tylko informuję. Dziedziczenie nie jest jedynym sposobem budowania zależności w kodzie. Tu zwykłe interfejsy wystarczają. Dodatkowo polimorfizm dynamiczny działa także dla referencji a nie tylko dla wskaźników. Preferuj referencje i alokowanie na stosie a nie na stercie. Jeśli przemyślisz strukturę, nie będzie "gołego new" ani "gołego delete".

komentarz 3 kwietnia 2019 przez Poczprogramista123 Bywalec (2,900 p.)
Dodales w nawiasie gdzie destruktor dla tego tak pomyslalem, ale nie wazne. Bd wdzieczny w takim razie jak wskazesz te inne drogi na budowaniu tych zaleznosci. Tez pojecie interfejsu w tym kontekscie nie zabardzo jest dla mnie zrozumiane. Przeciez kazdy obiekt gry: mario, wrog, item ma wspolne cechy dlatego wprowadzenie CRootGamaObejct i dziedziczenia z niego wydaje mi sie bardzo intuicyjne w tym przypadku. A jak mam inaczej to zrobic bo mam dwa rodzaje obiektow. Te ktore sa animacja albo zwyklym spritem. Dlatego wprowadzilen szablon.
komentarz 3 kwietnia 2019 przez mokrowski Mędrzec (158,660 p.)

No to (oczywiście w szczegółach pewnie metody będą miały inne nazwy), wystarczy implementacja interfejsów np. Animation i Sprite. Załóżmy że Animation ma metodę step() a Sprite metodę move(): 

class Animation {
public:
    virtual void step() = 0;
    virtual ~Animation() = default; // Potrzebny jeśli gdzieś będziesz trzymał referencje/wskaźniki na "coś co jest animowane"
};

class Sprite {
public:
    virtual void move() = 0;
    virtual ~Sprite() = default; // j.w. na "coś co jest spritem"
};

class Mario: public Animation, public Sprite {
public:
    void step() override {}
    void move() override {}
};

int main() {
    Mario mario;
}

Podobnie implementujesz inne zdolności. Myślę że nie potrzebujesz niczego więcej.

Taniej osiągniesz tę samą funkcjonalność z użyciem CRTP bez virtual https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern . Radzę jednak na wstępie zrobić tradycyjnie z użyciem interfejsów a więc i virtual czyli polimorfizmem dynamicznym.

 

1 odpowiedź

0 głosów
odpowiedź 2 kwietnia 2019 przez j23 Mędrzec (195,240 p.)

Jeśli już, to tak zrób:

template<class T>
class CGameObj
{
private: 
    virtual void action(T *obj) = 0;
 
};
 
template<class T> 
class CItem: public CGameObj<T>
{
private: 
    void action(T *obj) override {}
 
};

Tylko licz się z tym, że dla różnych typów T klasy będą miały różne klasy bazowe, więc nici z polimorfizmu.

komentarz 2 kwietnia 2019 przez Poczprogramista123 Bywalec (2,900 p.)
Dzięki. Przybliżenie tematu pokazałem w komentarzu. Bd wdzięczny jak zerkniesz :)

Podobne pytania

0 głosów
1 odpowiedź 211 wizyt
+1 głos
0 odpowiedzi 137 wizyt
0 głosów
0 odpowiedzi 711 wizyt
pytanie zadane 29 czerwca 2017 w Java przez Kriszu Nowicjusz (200 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

...