Menadzer zasobow, szablon klasy bazowej

0

Witajcie.
Próbuje napisać sobie menadżer zasobów.
Założyłem już wcześniej temat - link: http://4programmers.net/Forum/C_i_C++/258265-menadzer_zasobow?p=1182790#id1182790
(Nowy wątek zakładam gdyż sadze że nie należy tamtego' odgrzewać')


Właściwie napisałem już ów menadżer - nawet działa ;) ale uznałem że jest zbyt skomplikowany, że można zrobić to prościej.
W związku z powyższym zacząłem od nowa.
Jestem przy tworzeniu kontenerów zasobów.
Miałem w planach coś tego:

Klasa CResourceContainerBase jest interfejsem i jest klasą abstrakcyjna
Udostępnia metodę getResource();

Klasa przechowująca teksturę CContainerTexture
dziedziczy po CResourceContainerBase,implementuje metodę getResource();

Przykładowe użycie (tak miało być):

CResourceContainerBase * m_ptr = newCContainerTexture("sciezkaDoPliku");

Jednak gdy to obmyślałem zapomniałem że metoda getResource musi coś zwracać
Dodałem wiec szablon do klasy bazowej:

template<class TypeStoredResource>

Ostatecznie mam coś takiego:
CResourceContainerBase:

template<class TypeStoredResource>
class CResourceContainerBase
{
public:
   virtual TypeStoredResource * getResource()=0;
protected:
   CResourceContainerBase(){};
  virtual ~CResourceContainerBase(){};
};

CContainerTexture:

class CContainerTexture final
      :public CResourceContainerBase<sf::Texture>
{
public:
   CContainerTexture(std::string pathResFile);
  ~CContainerTexture();

   sf::Texture * getResource() override;
private:


};
CContainerTexture::CContainerTexture(std::string pathResFile)
{

}

CContainerTexture::~CContainerTexture()
{

}
sf::Texture * CContainerTexture::getResource()
{

}

Jednak by tego użyć należy zrobić tak:

CResourceContainerBase<sf::Texture> * m_ptr = new CContainerTexture("sciezkaDoPliku");

I tu leży mój problem.
Chce wyeliminować potrzebę wpisywania:

<sf::Texture>///<---przy okazji: jak to się fachowo nazywa?

Tak by legalne było coś takiego:

CResourceContainerBase* m_ptr = new CContainerTexture("sciezkaDoPliku");

Czy ktoś ma pomysł jak to osiągnąć - jestem na początku pisania więc wszelkie zmiany wchodzą w grę.

0

Pomyślałem sobie by zmodyfikować klasę:CResourceContainerBase w ten sposób
ze wyrzucę szablon a metoda getResource będzie zwracać wskaźnik typu void.
Jednak to rozwiązanie mało C++-owe.
Próbowałem zaimplementować swoje roziąwazanie w i stwierdziłem ze to nie to.

Coś w tym guście mi wyszlo.

class CResourceContainerBase
{
public:
protected:
   CResourceContainerBase(){};
  virtual ~CResourceContainerBase(){};
   virtual void * getResourceFromContainer()=0;
};

Czy istnieje jakiś sposób by stworzyć klasę(interfejs) narzucającą na wszystkie klasy które z niej dziedziczą implementacje metody która możne zwrócić dane dowolnego typu?

PS: Przyszedł mi jeszcze do głowy pomysł by zrezygnować z interfejsu ale to ostateczność.

Mam jeszcze pytanie: Co robi i jakie konsekwencje ma ten zapis w szablonie bo kompilator dopuszcza ten zapis (to już tak z ciekawości)

template<class TypeStoredResource = sf::Texture>//Ten zapis po lewej: = sf::Texture
class CResourceContainerBase
{
public:
    virtual TypeStoredResource * getResource()=0;
protected:
   CResourceContainerBase(){};
  virtual ~CResourceContainerBase(){};
};
0

Przepraszam za post ale nie mam pomysłu jak rozwiązać problem i potrzebuje rady/opinii osób bardziej doświadczonych.
@Azarien
@spartanPAGE
@Patryk27
@Shalom

0

Nie bardzo rozumiem twój problem, bo to te twoje próby rozwiązania problemu totalnie nie mają sensu.

  1. Jeśli chcesz przechowywać obiekty różnego typu to musisz tam mieć szablon, albo surowe pointery
  2. Próba "pozbycia się" parametru szablonu w deklaracji typu jest dla mnie niezrozumiała. Wyobraź sobie że mamy taki kod (zakładając że jest możliwość usunięcia tego parametru generycznego tak jakbys chciał)
CResourceContainerBase* xyz = NULL;
if(random()){
    xyz = CContainerTexture("sciezkaDoPliku");
}else{
    xyz = CContainerRower("sciezkaDoPliku");
}
typ zmienna = xyz.getResource();

Moje pytanie brzmi: jakiego typu będzie zmienna i jak wg ciebie kompilator miałby się tego domyslić na etapie kompilacji.
3. Ten zapis który pokazałeś na końcu tworzy tzw specjalizacje szablonu dla pewnego typu, niemniej w takim przykładzie nie bardzo ma to sens. Równie dobrze mógłbyś tam mieć teraz klasę bez szablonu w ogóle.

Od razu zaznaczam że wymiataczem z szablonów w C++ nie jestem i mogę pisać głupoty bo dawno sie tym nie zajmowałem.

0
kacper546 napisał(a):

Chce wyeliminować potrzebę wpisywania:

<sf::Texture>///<---przy okazji: jak to się fachowo nazywa?

Template instantiation

kacper546 napisał(a):

Tak by legalne było coś takiego:

CResourceContainerBase* m_ptr = new CContainerTexture("sciezkaDoPliku");

Czy ktoś ma pomysł jak to osiągnąć - jestem na początku pisania więc wszelkie zmiany wchodzą w grę.

auto

kacper546 napisał(a):

Pomyślałem sobie by zmodyfikować klasę:CResourceContainerBase w ten sposób
ze wyrzucę szablon a metoda getResource będzie zwracać wskaźnik typu void.

Broń cię panie boże.

kacper546 napisał(a):

Czy istnieje jakiś sposób by stworzyć klasę(interfejs) narzucającą na wszystkie klasy które z niej dziedziczą implementacje metody która możne zwrócić dane dowolnego typu?

To się nazywa template.

kacper546 napisał(a):

Mam jeszcze pytanie: Co robi i jakie konsekwencje ma ten zapis w szablonie bo kompilator dopuszcza ten zapis (to już tak z ciekawości)

template<class TypeStoredResource = sf::Texture>//Ten zapis po lewej: = sf::Texture
class CResourceContainerBase
{
public:
    virtual TypeStoredResource * getResource()=0;
protected:
   CResourceContainerBase(){};
  virtual ~CResourceContainerBase(){};
};

Defaultowy parametr class template.

Odnośnie twojego problemu - nie rób jednego, wielkiego managera zasobów, zdefiniuj managery zasób per konkretny zasób.

1

Nie bardzo rozumiem po co ci osobna klasy CResourceContainerBase i CContainerTexture.

Zobacz jak się robi kontenery generyczne: w bibliotece standardowej masz std::vector, któremu się podaje typ elementu (twoje TypeStoredResource) i już, np. vector<sf::Texture>.

0

Nie bardzo rozumiem po co ci osobna klasy CResourceContainerBase i CContainerTexture.

Chcę zrobić menadżer zasobów - jedną klasę która by zasobami zarządzała

(PSEUDO KOD)

class Manager
{
   public:
   private:
   std::map<int,CResourceContainerBase*>
};

Jeżeli będę zmuszony pisać

 CResourceContainerBase<TypZasobu> * m_ptr;

Będę musiał zrobić kilka menadżerów (od trawy tekstury itd) a potem menadżer tych menadżerów (fasade na te menadzery)
Tak właśnie zrobiłem wcześniej a teraz kombinuje jak tego uniknać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1