Tue
29
Jan 2008
Wpadłem ostatnio na pomysł, żeby się z wami podzielić drobnym rozwiązaniem, które wymyśliłem i które stosuję od dawna w swoim kodzie. Jako przykład weźmy manager zasobów. U mnie jest jeden ogólny, a każda klasa zasobu dziedziczy ze wspólnej klasy bazowej IResource. Są więc klasy pochodne takie jak D3dTexture czy FmodSound. Zasobów używam przez wskaźnik, ale ponieważ ich lista jest zapisana w pliku tekstowym, trzeba taki wskaźnik najpierw pobrać na podstawie nazwy. Trzeba przy tym zrzutować otrzymany zasób w dół na określony typ pochodny. Można to zrobić tak:
res::D3dTexture *Tex = (res::D3dTexture*)res::g_Manager->MustGetResource(L"Potwór01"); Tex->Cośtam();
lub bezpieczniej ze względu na typ:
res::D3dTexture *Tex = dynamic_cast<res::D3dTexture*>(res::g_Manager->GetResource(L"Potwór01")); if (Tex == NULL) throw Error(...); Tex->Cośtam();
Mój pomysł polega na napisaniu metody szablonowej, która ukryje rzutowanie:
template <typename T>
T * MustGetResourceExf(const wstring &Name)
{
return static_cast<T*>(MustGetResource(Name));
}
I jej wersji wolniejszej ale bezpieczniejszej:
template <typename T>
T * MustGetResourceEx(const wstring &Name)
{
IResource *R = MustGetResource(Name);
if (typeid(*R) != typeid(T)) throw Error(...);
return static_cast*lt;T*>(R);
}
Używa się ich tak:
res::D3dTexture *Tex = res::g_Manager->MustGetResourceEx<res::D3dTexture>(L"Potwór01"); Tex->Cośtam();
Prawda, że bardziej eleganckie? :) Gdyby ktoś pytał, przedrostek "Must" oznacza u mnie, że w przypadku nieznalezienia zasobu o podanej nazwie rzucony zostaje wyjątek, w przeciwieństwie do metod bez niego, które w takim przypadu zwracają NULL.
Comments | #c++ #algorithms Share