Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Przekazywanie prywatnych obiektów innym klasą.

Ostatnio zmodyfikowano 2018-06-25 17:42
Autor Wiadomość
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.
C/C++
#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).
P-171671
michal11
» 2018-06-25 14:03:51
Twoja klasa Game powinna mieć funkcję
C/C++
GetWindSize()
{
    m_wind.GetSize();
}
P-171672
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
C/C++
#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;
   
    //Tego chce uniknac
    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ć?
P-171675
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.
P-171677
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?
P-171678
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).
P-171680
michal11
» 2018-06-25 17:05:20
C/C++
//Tego chce uniknac
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.
P-171682
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.
P-171683
« 1 »
  Strona 1 z 1