marianexyx Temat założony przez niniejszego użytkownika |
Przekazywanie obiektowi referencji do nieistniejącego obiektu » 2016-10-01 10:14:48 Zamieniam kod moich aplikacji na obiektowy, gdzie przy okazji uczę się jak to robić, bo nigdy wcześniej nie wchodziłem głębiej w OOP. Na pewnym etapie pisania pojawiła mi się potrzeba przekazania nowo tworzonemu obiektowi referencji do obiektu, który jeszcze nie istnieje. Nie mogę zamienić kolejności tworzenia tych obiektów, bo drugi tak samo chce zawierać ten pierwszy w swym konstruktorze. class B;
class A { private: B * _pB; public: A( B * pB ) { _pB = pB } }
class B { private: A * _pA; public: B( A * pA ) { _pA = pA } }
A obiektA( & obiektB ); B obiektB( & obiektA ); Dostaję oczywisty błąd: error: 'obiektB' was not declared in this scope Jak mogę zatem przekazać obiektowi referencję do innego obiektu, który w powyższej formie nie mógłby być zadeklarowany wcześniej? |
|
jankowalski25 |
» 2016-10-01 11:26:41 1. Dokładasz domyślny konstruktor, gdzie ustawiasz wskaźnik na zero. 2. Tworzysz pierwszy obiekt domyślnym konstruktorem. 3. Tworzysz drugi obiekt przekazując pierwszy jako argument. 4. Tworzysz trzeci obiekt przekazując drugi jako argument. 5. Pozbywasz się pierwszego obiektu. 6. Zapewniasz, że obiekt drugi i trzeci są poprawnie utworzone (likwidujesz skutki uboczne użycia pierwszego obiektu, jeśli takie występują).
Dopisano: A nie wystarczy przekazać pustego wskaźnika do konstruktora? |
|
michal11 |
» 2016-10-01 15:10:33 Nie wiem co robisz ale najprawdopodobniej robisz to źle, stworzyłeś cykliczne zależności a to oznacza, że masz coś źle zaprojektowane. Pokaż jakiś konkretniejszy kod. |
|
marianexyx Temat założony przez niniejszego użytkownika |
» 2016-10-01 18:34:04 Starałem się okroić kod z większości zbędnych elementów przy tym zagadnieniu. komunikacja.h - klasa która na życzenie użytkownika wyrzuca informacje o stanie systemu, oraz odpowiada za przepływ informacji po aplikacji, jak i poza nią #ifndef komunikacja_h #define komunikacja_h
class cServoA; class cServoB; class cServoC; class cServoD; class cSilnik; class cRamie;
class cKomunikacja { private: bool _bPokazujeInfo; cServoA * _pServoA; cServoB * _pServoB; cServoC * _pServoC; cServoD * _pServoD; cServoEF * _pSilnikE; cServoEF * _pSilnikF; cRamie * _pRamie; public: cKomunikacja( cServoA * pServoA, cServoB * pServoB, cServoC * pServoC, cServoD * pServoD, cSilnik * pServoE, cSilnik * pServoF, cRamie * pRamie ); void PokazPozycjeRamienia(); void PrzygotujOdpowiedzNaRdzen( String sPolecenieRdzenia ); };
#endif komunikacja.cpp #include "komunikacja.h"
cKomunikacja::cKomunikacja( cServoA * pServoA, cServoB * pServoB, cServoC * pServoC, cServoD * pServoD, cServoEF * pServoEF, cRamie * pRamie ) { _bPokazujeInfo = false; _pServoA = pServoA; _pServoB = pServoB; _pServoC = pServoC; _pServoD = pServoD; _pSilnikE = pServoE; _pSilnikF = pServoF; _pRamie = pRamie; }
void cKomunikacja::PokazPozycjeRamienia() { if( _bPokazujeInfo == true ) { Serial.print( "kp = " ); Serial.print( _pServoA.getKat() ); Serial.print( ", alpha= " ); Serial.print( _pServoB.getKat() ); Serial.print( ", beta= " ); Serial.print( _pServoC.getKat() ); if(( int ) _pServoC.getKat() >= 157 ) Serial.print( "!!!" ); Serial.print( ", fi= " ); Serial.println( _pServoD.getKat() ); Serial.print( " | y = " ); Serial.print( _pRamie.getYtemp() ); Serial.print( ", z = " ); Serial.print( _pRamie.getZtemp() ); Serial.print( ", z_upgr = " ); Serial.print( _pRamie.getZtemp() ); if(( int ) dZmiennaDoPokazania >= 236 ) Serial.print( "!!!" ); } }
void cKomunikacja::PrzygotujOdpowiedzNaRdzen( String sPolecenieRdzenia ) { } servo_a.h - jedna z kilku tego typu podobnych do siebie klas #ifndef servo_a_h #define servo_a_h
#include "silnik.h" #include "komunikacja.h"
class cServoA : public cSilnik { private: public: cServoA( cKomunikacja * pKomunikacja ) { _pKomunikacja = pKomunikacja; } String Trash() { _pKomunikacja->PrzygotujOdpowiedzNaRdzen( "r_trash" ); String sXYprzyResecie = "(170,240)"; return sXYprzyResecie; } };
#endif main.cpp - tutaj tworzę obiekty klas cServo, które mają możliwość w niektórych miejscach używać metod klasy cKomunikacja, która zajmuje się wymianą informacji pomiędzy elementami systemu (np. metodą PrzygotujOdpowiedzNaRdzen() ). Z drugiej strony chcę w obiekcie klasy cKomunikacja używać wartości z pól obiektów klasy cServo, m.in. do wyświetlania stanu wszystkich Servo (cKomunikacja::PokazPozycjeRamienia) na zawołanie w np. pliku main.cpp #include "silnik.h" #include "komunikacja.h" #include "ramie.h" #include "servo_a.h" #include "servo_b.h" #include "servo_c.h" #include "servo_d.h" #include "servo_ef.h"
cServoA ServoA_kp( 2, "kp", 15, 175, & LCD_angle, & LCD_pos, & Komunikaty ); cServoB ServoB_alpha( 3, "alpha", 0, 180, & LCD_angle, & LCD_pos ); cServoC ServoC_beta( 4, "beta", 24, 157, & LCD_angle, & LCD_pos ); cServoD ServoD_fi( 5, "fi", 45, 180, & LCD_angle, & LCD_pos, & Komunikaty ); cServoEF ServoE_ks1( 6, "ks1", 82, 131, & LCD_angle, & LCD_pos, & Komunikaty ); cServoEF ServoF_ks2( 7, "ks2", 200 - 131, 200 - 82, & LCD_angle, & LCD_pos );
cKomunikacja Komunikaty( & ServoA_kp, & ServoB_alpha, & ServoC_beta, & ServoD_fi, & ServoE_ks1, & ServoF_ks2, & Ramie );
No i w powyższym przykładzie mam owe referencje do obiektów, które jeszcze nie istnieją. W razie czego wrzucam jeszcze mój aktualny cały kod: https://github.com/marianexyx/arduino_chess_control/tree/master/kinematyka_odwrotna |
|
carlosmay |
» 2016-10-01 21:30:35 Klasa cKomunikacja ma więcej niż jedną odpowiedzialność. Odpowiada za komunikację i wyświetla dane o systemie. To powinny być dwie klasy. Prawdopodobnie rozwiąże to problem z używaniem klas na krzyż.
Unikaj zależności cyklicznych, klasa B zna klasę A, to klasa A nie zna klasy B. Jeśli musisz mieć taką zależność tworzysz klasę C implementującą interfejs odpowiadający potrzebom.
|
|
marianexyx Temat założony przez niniejszego użytkownika |
» 2016-10-02 13:17:30 @carlosmay: Miałem przez chwilę taką myśl i jak się nad tym zastanowiłem teraz przy kodzie, to rzeczywiście będzie tak jak mówisz i tak zatem zrobię. Dzięki za radę. |
|
« 1 » |