Forum Sveta kompjutera

Nazad   Forum Sveta kompjutera > Test Run > Programiranje
Uputstvo Članstvo Kalendar Današnje poruke Pretraži

Programiranje Programski jezici, tehnike, alatke...

Odgovor
 
Alatke vezane za temu Vrste prikaza
Stara 29.9.2009, 1:24   #1
fingerprint
Veteran
 
Član od: 5.11.2006.
Lokacija: Dark Side Of The Moon
Poruke: 1.121
Zahvalnice: 394
Zahvaljeno 594 puta na 222 poruka
Slanje poruke preko MSN-a korisniku fingerprint Slanje poruke preko Yahooa korisniku fingerprint
Određen forumom Pretprocesorsko generisanje koda (C++)

Da li vam se nekad desilo da imate takav slucaj, da vam trebaju klase (koje trenutno ne znate da li će postojati) koje prate neki šablon, ali ih je nemoguće izraziti template-ovima?

Daću primer koji sam ja imao večeras. Imam apstraktne listener klase :
Kod:
struct mouse_listener
{
virtual void mouse_down (const SDL_MouseButtonEvent &e, Uint32 time, Uint32 rtime) = 0;
virtual void mouse_up (const SDL_MouseButtonEvent &e, Uint32 time, Uint32 rtime) = 0;
};
struct mouse_motion_listener
{
virtual void mouse_move (const  SDL_MouseMotionEvent &e, Uint32 time, Uint32 rtime) = 0;
virtual void mouse_drag (const  SDL_MouseMotionEvent &e, Uint32 time, Uint32 rtime) = 0;
};
E, sad, za svaki od ovih listenera, hocu da napravim emitor klasu, koja ce biti izvedena iz date listener klase, i treba da se ponasa slicno kao event u C# : dodajem listenere eventu, pa kad pozovem neki njegov metod, on automatski pozove taj metod za svakog listenera. Na primer :
Kod:
class mouse_event_emitter : public mouse_listener
	{ 
	mouse_listener_t listeners;
	public:
	void add_mouse_listener( mouse_listener *_listener )
		{
		listeners.push_back(_listener);
		}
	void remove_mouse_listener( mouse_listener *_listener )
		{
		mouse_listener_t::iterator iter = std::find(listeners.begin(), listeners.end(), _listener);
		if( iter != listeners.end() )
			listeners.erase( iter );
		}

	void mouse_down (const SDL_MouseButtonEvent &e, Uint32 now, Uint32 rnow)
		{
		for( mouse_listener_t::iterator iter = listeners.begin(); iter != listeners.end(); ++iter )
			(*iter)->mouse_down( e, now, rnow );
		}
	void mouse_up (const SDL_MouseButtonEvent &e, Uint32 now, Uint32 rnow)
		{
		for( mouse_listener_t::iterator iter = listeners.begin(); iter != listeners.end(); ++iter )
			(*iter)->mouse_up( e, now, rnow );
		}
};
Prilično je jasno da je ovo naporan posao, treba napisati event emitor za svaki event listener, i funkciju za svaki event (dosta kopiranja koda, podložno greškama). Da bih rešio ovaj problem, napisao sam par makroa, pomocu kojih sam definisao "jezik" za pravljenje ovih emitor klasa. Na taj način sam olakšao posao (ima tu dosta listener klasa, nisam napisao sve, naravno). Evo makroa :

Kod:
#define OPEN_CLASS(name)\
	class name##_event_emitter : public name##_listener\
	{ name##_listener_t listeners;\
	public:\
	void add_##name##_listener( name##_listener *_listener )\
	{\
	listeners.push_back(_listener);\
	}\
	void remove_##name##_listener( name##_listener *_listener )\
	{\
	name##_listener_t::iterator iter = std::find(listeners.begin(), listeners.end(), _listener);\
	if( iter != listeners.end() )\
		listeners.erase( iter );\
	}


#define CLOSE_CLASS\
	};

#define EVENT(name, eventname, SDLEVENT)\
	void eventname (const SDLEVENT &e, Uint32 now, Uint32 rnow)\
	{\
	for( name##_listener_t::iterator iter = listeners.begin(); iter != listeners.end(); ++iter )\
		(*iter)->eventname( e, now, rnow );\
	}
Sada, sve što treba da uradim da bih definisao emitor klasu za bilo koju listener klasu je (na primeru par emitora koji bi inace bili katastrofa posao):

Kod:
OPEN_CLASS(mouse)
	EVENT(mouse, mouse_down, SDL_MouseButtonEvent)
	EVENT(mouse, mouse_up, SDL_MouseButtonEvent)
CLOSE_CLASS

OPEN_CLASS(mouse_motion)
	EVENT(mouse_motion, mouse_move, SDL_MouseMotionEvent)
	EVENT(mouse_motion, mouse_drag, SDL_MouseMotionEvent)
CLOSE_CLASS


OPEN_CLASS(key)
	EVENT(key, key_down, SDL_KeyboardEvent)
	EVENT(key, key_up, SDL_KeyboardEvent)
	EVENT(key, key_press, SDL_KeyboardEvent)
CLOSE_CLASS

OPEN_CLASS(update)
	EVENT_NOCLASS(update, update)
CLOSE_CLASS
//I kompajler ce resiti ostalo :)
Jeste li vi nekad imali sličan problem? Ako jeste, kako ste ga rešili? Ako imate, dajte neki interesantan primer korisnog korišćenja C/C++ makroa.
fingerprint je offline   Odgovor sa citatom ove poruke
Odgovor

Bookmarks sajtovi

Tagovi
c++, preprocesor, preprocessor, pretprocesor


Vaš status
Ne možete postavljati teme
Ne možete odgovarati na poruke
Ne možete slati priloge uz poruke
Ne možete prepravljati svoje poruke

BB kod: uključeno
Smajliji: uključeno
[IMG] kod: uključeno
HTML kod: isključeno


Slične teme
tema temu započeo forum Odgovora Poslednja poruka
Generisanje serijskih brojeva pixel Programiranje 3 8.8.2009 2:12
Generisanje imena, titula, ideja za RPG pricu... BrunnenG Zanimljive Web lokacije 1 9.5.2009 2:32
Menjanje koda za smajlije Guterill Forum o forumu 14 26.1.2008 19:04
Objasnjenje koda C++ Cyrus_M Programiranje 5 10.1.2008 23:30
Svadja oko koda Obliviona Andross Pravljenje igara 5 27.1.2007 21:51


Sva vremena su po Griniču +2 h. Sada je 4:21.


Powered by vBulletin® verzija 3.8.7
Copyright ©2000–2024, vBulletin Solutions, Inc.
Hosted by Beograd.com