Wuwus1 Temat założony przez niniejszego użytkownika |
Przekazywanie prywatnych obiektów innym klasą. » 2018-06-25 12:50:03 Od paru dni próbuję napisać klasę, która jest takim łączem pomiędzy poszczególnymi modułami programu. np mam klasę gra, która zawiera w sobie prywatny obiekt okno, teraz chcę przekazać do klasy gracz wielkość okna, ale nie chcę przekazywać wszystkich funkcji obiektu okno. Z tego, co poczytałem w internecie, tworzenie wartości globalnych jest złym pomysłem, więc wymyśliłem coś takiego. #include <iostream>
class Getter;
class Wind { public: Wind() { } ~Wind() { } void GetSize() const { std::cout << x << std::endl; std::cout << y << std::endl; } private: int x = 10; int y = 12; };
class Game { public: Game() { } ~Game() { } friend Getter; private: Wind m_wind; };
class Getter { public: Getter() { } ~Getter() { } void GetWind( Game & w ) { h_wind = & w; } void GetWindSize() { h_wind->m_wind.GetSize(); } private: Game * h_wind; };
int main() { Game maingame; Getter maingetter; maingetter.GetWind( maingame ); maingetter.GetWindSize(); system( "pause" ); return 0; } . Nie wiem, czy to najbardziej efektywny sposób, więc chciałem się zapytać kogoś, kto pracował nad jakimś większym projektem i dowiedzieć się jak wygląda w nim takie zarządzanie i przekazywanie danych między poszczególnymi modułami. Próbowałem szukać na ten temat w internecie, ale nic nie znalazłem, może ktoś przynajmniej wie co wyszukać w Google, aby dowiedzieć się więcej (Może być po angielsku). |
|
michal11 |
» 2018-06-25 14:03:51 Twoja klasa Game powinna mieć funkcję GetWindSize() { m_wind.GetSize(); }
|
|
Wuwus1 Temat założony przez niniejszego użytkownika |
» 2018-06-25 15:55:40 No tak, ale strasznie nie lubię robić czegoś takiego, że moja funkcja (game) zwraca wartość z drugiej funkcji (wind) takie podwójne wywoływanie tej samej funkcji. W przypadku, gdybym miał klasę, która nie potrzebuje wielkości okna, ale w niej znajdował, by się obiekt prywatny, który by tej wartości potrzebował powstaje łańcuch funkcji przekazujących sobie wartość np #include <iostream>
class Okno { public: Okno() { } ~Okno() { } int Liczba() { return 5; } };
class CheWartosc { public: CheWartosc() { } ~CheWartosc() { } void Przyjmuje( int & var ) { std::cout << var << std::endl; } };
class Gracz { public: Gracz() { }; ~Gracz() { }; void DostarczWartosc( int var ) { m_ChceWartosc.Przyjmuje( var ); } private: CheWartosc m_ChceWartosc; };
int main() { Okno m_wind; Gracz m_player; m_player.DostarczWartosc( m_wind.Liczba() ); system( "pause" ); return 0; }
Gdybym miał dostarczyć więcej wartości do obiektu ChceWartosc to w obiekcie Game musiałbym napisać kolejne funkcje przekazujące te wartości. Powstaje taki węzeł niepotrzebnych powiązań między obiektami. Czy da się jakoś od tego uchronić? |
|
garlonicon |
» 2018-06-25 16:05:59 takie podwójne wywoływanie tej samej funkcji |
A gdzie tam, rzuć okiem na kod asma w godbolt.org, jak użyjesz GCC z flagą -O2, to całość uprości się do samego maina i wszystkie funkcje zostaną wrzucone jako inline , instrukcja call wystąpi tylko przy wywołaniach do std::basic_ostream (jako std::cout ) oraz do zbędnego i nieprzenośnego wywołania funkcji std::system . Teraz za wcześnie na optymalizacje, zacznij cokolwiek przyspieszać dopiero wtedy, gdy będziesz miał coś, co działa za wolno. |
|
Wuwus1 Temat założony przez niniejszego użytkownika |
» 2018-06-25 16:14:03 Dobrze wiedzieć, że tak to zostanie zoptymalizowane, jednak zawsze gdy próbuję napisać coś większego to moje klasy mają za dużo funkcji przekazujących dane i we wszystkim się plącze. Przypomina to trochę spaghetti code. Czy jest jakiś sposób, by temu zapobiec? |
|
jankowalski25 |
» 2018-06-25 16:29:48 Jakie spaghetti? Makaron będzie wtedy, gdy będziesz miał jednego wielkiego maina bez żadnych klas, gdy kod będzie używał kilku zmiennych wielokrotnie do różnych celów i gdy nie będzie się dało wyodrębnić samodzielnie działającego kawałka, który można edytować bez ruszania całej reszty. Masz podział na klasy, więc ciągnij to dalej. W miarę rozwoju projektu powinny się z tego wyklarować klocki działające niezależnie od całej reszty. A tym, że w C++ nie da się zaimplementować właściwości tak łatwo, jak w C#, to się na razie nie przejmuj (a jak jest tego więcej, to możesz utworzyć prosty szablon opakowujący poszczególne typy, ustawić składowe jako publiczne, a później ewentualnie podmienić domyślną implementację w razie potrzeby; zwykle jednak ręcznie napisane settery i gettery są wystarczające). |
|
michal11 |
» 2018-06-25 17:05:20 m_player.DostarczWartosc( m_wind.Liczba() );
a dla mnie to poprawny fragment kodu, zdecydowanie lepszy niż jakieś publiczne zmienne czy deklaracje przyjaźni. Gdybym miał dostarczyć więcej wartości do obiektu ChceWartosc to w obiekcie Game musiałbym napisać kolejne funkcje przekazujące te wartości. |
albo opakować te dane w jakąś strukturę i przekazywać strukturę. Powstaje taki węzeł niepotrzebnych powiązań między obiektami. Czy da się jakoś od tego uchronić? |
Generalnie to bardzo zależy od kontekstu i tego co chcesz napisać, nie da się opisać idealnych zasad i reguł które zawsze zadziałają, poprawne tworzenie klas i ich interfejsów to część "rzemiosła" programisty które zdobywa się wraz z doświadczeniem. |
|
Wuwus1 Temat założony przez niniejszego użytkownika |
» 2018-06-25 17:42:59 Bardzo dziękuję za wypowiedź i za porady wszystkich, zyskałem dużo wiedzy i myślę, że tym razem uda mi się dokończyć mój projekt. |
|
« 1 » |