C++ klasy a ładowanie dźwiękow


(arekk-99) #1

W jaki sposób zrobić klasę Audio zarządzającą dźwiękiem tak, by za każdym wywołaniem tej klasy w innej klasie nie musieć ładować dźwięków?
Mam napisaną klasę Audio zarządzającą dźwiękiem i gdy chcę odtworzyć dźwięk w klasie player, to muszę znów je załadować. Ale to jest chyba już lekka przesada, bo załadowane dźwiękii były w klasie Engine.


(Fizyda) #2

Nie wiem czy rozumiem problem. Dźwięki ładujesz gdy utworzysz obiekt tej klasy? Jeśli tak to rozwiązaniem będzie albo przekazywanie referencji do tego obiektu do pozostałych klas lub co jest mniej ładnym rozwiązaniem bo wprowadza swego rodzaju zmienne globalne zastosowanie wzorca projektowego singleton.


(arekk-99) #3

Nie, wywołuję funkcje loadSounds. Obiekt tworzy się bez ładowania dźwięków właśni dopiero potem je ładuję.


(Fizyda) #4

Dobra ale w konkretnym obiekcie ładujesz dźwięki - dźwięki są związane z konkretnym obiektem?


(arekk-99) #5

Takie założenie miałem, ale do tego musiałbym zrobić kilka klas no i jedną główną, sterującą tymi wszystkimi, ale na to nie mam koncepcji. No chyba, zę da się w jakiś sposób w jakimś głównym pliku typu main.cpp zadeklarować tą klasę, tam załadować dźwięki i jakimś externem się do tego odwoływać w plikach pozostałych. No bo na razie w każdej klasie inicjuję klasę Audio, co jest chore, bo za każdym razem muszę dźwięki ładować.


(Fizyda) #6

No to na takie coś masz dwa rozwiązania które podałem w pierwszym poście. Albo przekazujesz przez referencję do wszystkich modułów programu które potrzebują tego obiektu raz utworzony obiekt z załadowanymi dźwiekami, albo robisz singletona, możesz się jeszcze poratować właściwościami i metodami statycznymi, ale z dwojga złego lepszy chyba będzie singleton.


(arekk-99) #7

Albo ja jestem półinteligentny, albo z tym przykładem na cpp0x jest coś nie tak
http://cpp0x.pl/kursy/Wzorce-projektowe/Wzorce-kreacyjne/singleton/161
no i nijak nie mam pojęcia jak to tu wrzucić
Oczywiście również nie da się dodać kodu, więc wysyłam archiwum zip
audioo.zip (3,0 KB)


(Fizyda) #8

Zerknąłem w kod i nic poza:

  1. ustawiasz konstruktor jako prywatny
  2. dodajesz statycznego propertisa typu swojej klasy
  3. dodajesz metodę statyczną w której tworzysz obiekt klasy jeśli nie istnieje, zapisujesz w statycznym propertisie i go zwracasz - jak w przykładzie

nic ponad to. Nawet specjalnie nie musisz modyfikować swojego kodu.


(arekk-99) #9

ale jak konstruktor będzie prywatny to przecież nie wywołam nigdzie tej klasy czyż nie?


(arekk-99) #10

No chyba, że wywołam metodę tworzącą konstruktor, ale czy to nie jest zabawa na około?


(Fizyda) #11

Po to jest singleton by utworzyć tylko jeden obiekt tej klasy i móc za pomocą metody statyczne zawsze się do niego dobrać w każdym miejscu programu. To nie jest zabawa na około tylko obejście braku zmiennych globalnych w OOP, jest to sposób raczej brzydki bo łamie to co miało OOP naprawić czyli hermetyzację, dlatego lepiej przekazywać obiekt przez referencję do pozostałych obiektów które go potrzebują użyć bo masz większą kontrolę nad tym gdzie ten obiekt jest dostępny. Singleton daje możliwość dostania się do obiektu wszędzie - w ramach całego programu.

Jest to fajny wzorzec i jednocześnie chyba najbardziej znienawidzony przez konserwatywnych programistów, dlatego trzeba się zastanowić 10 razy nad jego użyciem.


(arekk-99) #12

Czyli mogę sobie normalnie przez Audio audio; się odwołać do tego obiektu? i normalnie będzie wszystko załadowane


(arekk-99) #13

Nie bardzo to ogarniam. Zrobiłem coś takiego ale teraz nie wiem czy mam te funkcje zadeklarowac poza klasą czyco znowu.audio.zip (3,0 KB)


(Fizyda) #14

Tak jak w przykładzie - jako metodę statyczną. Swoją drogą czemu masz publiczne własności? Powinny być prywatne i ewentualnie jeśli jest taka potrzeba dodać do nich gettery i settery by zachować hermetyzację.


(arekk-99) #15

No to właśnie chyba zrobiłem tak jak w przykładzie, ale teraz wychodziłoby że musze te funkcje wyrzucić z klasy. No ale po co mam w nich używać Audio::init() jak nie mam zadnego operatora, bo i po co on tam?


(arekk-99) #16

a, no i jak wyrzucę te funkcję poza klasę, jjak w przykładzie, to i te sound_type i reszte enumów będę musiał wyrzucić, bo skoro mają być prywatne, to z poziomu funkcji do odtworzenia dźwięku się do nich nie dostanę.


(Fizyda) #17

Dostaniesz się przy użyciu odpowiednich metod (getterów i setterów). Init dalej robi to co robił, a metoda statyczna służy tylko po to by dostać referencję obiektu tej klasy.

Poczytaj o tym wzorcu bo mam wrażenie że nie rozumiesz idei.


(arekk-99) #18

No przecież piszę, że czytałem. 3 razy czytałem to samo i nadal nie ogarniam jak potem się dostać i po co mam wyrzucić te funkcje z klasy no i potem te metody które były prywatne, czyli te sound_type staną się dostępne dla wszystkich. No i i tak nie wiem… więc chyba zostanie to tak jak jest, tylko że szkoda mi pamięci


(Fizyda) #19

Pseudo kod:

//
// Najpierw prywatne właściwości
//
class Example {
	private:
		int jakas_zmienna;
	
	public:
		//chcesz móc ja odczytywać
		int getJakasZmienna() { return this->jakas_zmienna; }
		
		//chcesz móc ją modyfikować
		void setJakasZmienna(int wartosc) { this->jakas_zmienna = wartosc; }
}

// Gdzies w programie uzywasz:

...
	Example obiektExample();
	
	if(obiektExample.getJakasZmienna() == 0)
		obiektExample.setJakasZmienna(rand() + 1);
...

//
// To byla zwykla klasa, teraz taka ktora bedzei miala jedna instancje - singleton
//
class SingletonExample {
	private:
		SingletonExample();
		SingletonExample(S const&);	//bez implementacji
        void operator=(S const&); //bez implementacji
		int jakas_zmienna;
	
	public:
		static CSingleton & getInstance()
		{
			// konstruktor jest prywatny, tylko w obrebie danej klasy lub
			// zaprzyjaznionej mozesz wywolywac metody prywatne i masz dostep
			// do wlasnosci prywatnych czyli do konstruktora
			static CSingleton instance;
			
			return instance;
		}
		
		// .. jak w poprzednim przykladzie
}

// Gdzies w kodzie ...

...
	SingletonExample * obiektExample = SingletonExample::getInstance();
	
	obiektExample->setJakasZmienna(22);
	
	// tworzymy jakas inna klase w ktorej dzieje sie powiedzmy cos takieg:
	{
		SingletonExample * privateExample = SingletonExample::getInstance();
		
		privateExample->setJakasZmienna(33);
	}
	
	// wracamy do spowrotem
	obiektExample->getJakasZmienna(); // daje nam 33
...

// Gdzies indziej w kodzie, na lini czasu po operacjach wyzej ...

...
	SingletonExample * cos = SingletonExample::getInstance();
	
	cos->getJakasZmienna(); // dalej 33
...

Gdzieniegdzie mogłem popełnić błąd, np nie jestem pewny co do wskaźników i “pobierania singletona” czy na pewno jest to poprawnie zapisane w C++.
Prościej wytłumaczyć już nie umiem.


(arekk-99) #20

A pierwszy sposó”? Mam zwrócić całą klasę?