RazzorFlame Temat założony przez niniejszego użytkownika |
Sposób na uporządkowanie komponentów własnej biblioteki » 2014-10-27 19:31:00 Otóż pisząc bibliotekę wpadłem na pomysł stworzenia czegoś w stylu menedżera komponentów z mojej biblioteki. Zastanawiałem się co by tu zrobić i zaświeciła mi się lampka. Celem było umożliwienie programiście jak najłatwiejszego tworzenia i dostępu do komponentów. Tutaj przykład:
#include "stdafx.h"
#include <iostream>
using namespace std;
class CompA { public: int a; void draw() { cout << "A: " << a << endl; } CompA( int x = 0 ) { a = x; } };
class CompB { public: int a; void draw() { cout << "A: " << a << endl; } CompB( int x = 1 ) { a = x; } };
class CompC { public: int a; void draw() { cout << "A: " << a << endl; } CompC( int x = 2 ) { a = x; } };
class CompD { public: int a; void draw() { cout << "A: " << a << endl; } CompD( int x = 3 ) { a = x; } };
enum ECompReg_A { COMPONENT_A }; enum ECompReg_B { COMPONENT_B }; enum ECompReg_C { COMPONENT_C }; enum ECompReg_D { COMPONENT_D };
class ComponentRegister { CompA * cA; CompB * cB; CompC * cC; CompD * cD; public: ComponentRegister() { cA = NULL; cB = NULL; cC = NULL; cD = NULL; } void create( CompA * a ) { if( a ) cA = a; } void create( CompB * b ) { if( b ) cB = b; } void create( CompC * c ) { if( c ) cC = c; } void create( CompD * d ) { if( d ) cD = d; } CompA * get( ECompReg_A ) { return cA; } CompB * get( ECompReg_B ) { return cB; } CompC * get( ECompReg_C ) { return cC; } CompD * get( ECompReg_D ) { return cD; } };
int _tmain( int argc, _TCHAR * argv[] ) { ComponentRegister myReg; myReg.create( new CompA() ); myReg.create( new CompB() ); myReg.create( new CompC() ); myReg.create( new CompD() ); myReg.get( COMPONENT_A )->draw(); myReg.get( COMPONENT_B )->draw(); myReg.get( COMPONENT_C )->draw(); myReg.get( COMPONENT_D )->draw(); system( "pause" ); return 0; }
Jeszcze innym celem było ominięcie używania szablonów. Jak wiemy używanie szablonów w bibliotekach wymaga udostępnienie kodu (w tym przypadku klasy ComponentRegister). Poza tym, dodatkowym udogodnieniem jest to, że kod jest krótszy. Dla szablonów i tak musielibyśmy definiować funkcje pod określony typ. Co o tym rozwiązaniu sądzicie? Edit: A właśnie, jeżeli jakiś użytkownik biblioteki chciałby rozszerzyć klase ComponentRegister to wystarczy stworzyć klase dziedziczącą po ComponentRegister. |
|
pekfos |
» 2014-10-27 19:43:22 Nie zachwyca. (albo tylko taki przykład..) Czemu nie ma klasy bazowej dla wszystkich komponentów..? Czemu dodawanie nowego typu komponentu wymaga tak wielkich ingerencji? Czemu nie można mieć wielu obiektów jednego typu komponentu? I czemu dostęp do różnych komponentów ma lecieć przez ten 'fajny sposób', zamiast normalnie - po nazwach, które i tak muszą być dostępne. No dobra, jest sobie taki pomysł, ale to wygląda jak dodatkowa warstwa utrudniająca życie.. Podaj praktyczny przykład. I nazwę tematu popraw.. Jak wiemy używanie szablonów w bibliotekach wymaga udostępnienie kodu |
Od kiedy? |
|
RazzorFlame Temat założony przez niniejszego użytkownika |
» 2014-10-27 19:50:42 Czemu nie można mieć wielu obiektów jednego typu komponentu? |
enum ECompReg_VecA { COMPONENT_VECTOR_A };
class ComponentRegister { std::vector < CompA *> vCompA; public: ComponentRegister() { } void create( CompA * a ) { if( a ) vCompA.push_back( a ); } CompA * get( ECompReg_VecA, UINT id = 0 ) { if( vCompA.size() > 0 && id < vCompA.size() ) return vCompA[ id ]; else return NULL; } };
int _tmain( int argc, _TCHAR * argv[] ) { ComponentRegister myReg; myReg.create( new CompA( 1 ) ); myReg.create( new CompA( 2 ) ); myReg.create( new CompA( 3 ) ); myReg.get( COMPONENT_VECTOR_A )->draw(); myReg.get( COMPONENT_VECTOR_A, 1 )->draw(); myReg.get( COMPONENT_VECTOR_A, 2 )->draw(); system( "pause" ); return 0; }
Pisane bez kompilacji. Prawdą jest to że trzeba się troche trudzić, ale jeżeli ma to wyglądać schludnie i przyzwoicie to warto. Z resztą jak napisałem - kodu jest nawet mniej niż przy szablonach i nie trzeba męczyć się z plikami .inl, nie trzeba też udostępniać kodu. Edit: Jak wiemy używanie szablonów w bibliotekach wymaga udostępnienie kodu | Od kiedy? |
Czytałem gdzieś o tym, z resztą sugerowałem się głównie kodem źródłowym SFML gdzie autor właśnie pisze w ten sposób. Jeżeli nie trzeba tego robić to pardon, i prosiłbym o odesłanie do jakiegoś artykułu bo mi też by to ułatwiło prace. |
|
pekfos |
» 2014-10-27 19:54:56 kodu jest nawet mniej niż przy szablonach i nie trzeba męczyć się z plikami .inl, nie trzeba też udostępniać kodu. |
Nie musisz tego dzielić na pliki. Nie chcesz udostępniać kodu..? To nie pisz żadnych bibliotek, przecież trzeba udostępnić definicje klas.. Jak działasz na szablonach, to dojdzie do tego definicja jakichś dwóch, stricte dostępowych metod, na góra kilka linii - a i to nie zawsze. |
|
RazzorFlame Temat założony przez niniejszego użytkownika |
» 2014-10-27 20:04:39 Źle zrozumiałeś to co napisałem w pierwszym poście. Nie chodzi mi o to by nie udostępniać całego kodu... Chodzi o udostępnianie kodu definiującego metody lub funkcję. http://stackoverflow.com/questions/14238361/template-method-in-c-static-libraryJa tak czy siak jestem w stanie udostępniać kod zwłaszcza tak małej jego ilości, chodzi jednak o innych ludzi. Przecież gdybym chciał używać tego sam to nie miałbym po co tego tematu zakładać. Głównym powodem jest to, że użytkownikowi łatwiej będzie korzystać z tych wszystkich funkcji. Osobiście nie lubie bibliotek w których by dostać się do jakiegoś komponentu muszę znać ustaloną jego nazwę (wiadomo, trzeba je znać ale chodzi mi raczej o sytuacje gdy komponentów jest pełno i musisz znać dokładną nazwę każdego z osobna). Przykład: ID3D11Device * getDirectX11Device(); IDXGISharedResource * getDirectXSharedResource();
Można zastąpić z: ID3D11Device * get( EComp_Device ); IDXGISharedResource * get( EComp_SharedResource );
|
|
pekfos |
» 2014-10-27 20:38:31 A enumów nie trzeba tu znać? Dalej jest dokładna nazwa, której trzeba użyć. Dodajesz tylko dodatkową warstwę przerabiającą jedne nazwy na drugie. Taki mechanizm jest po prostu niewygodny. Twórca biblioteki musi pamiętać o jego utrzymywaniu, a w kodzie klienta hmm.. Albo będzie to niewygodne, albo nie będzie klientowi robiło różnicy, czy ten jeden raz pobierze jakąś wartość ręcznie, czy przez taki mechanizm. W najlepszym przypadku nie będzie to gorsze od standardowego podejścia, ale może tylko nie jestem w stanie znaleźć tu teraz istotnych zalet. |
|
RazzorFlame Temat założony przez niniejszego użytkownika |
» 2014-10-28 09:47:12 No nie wiem, mi by bylo lepiej używać tego sposobu. |
|
« 1 » |