CodeFun Temat założony przez niniejszego użytkownika |
Konstruktor obiektu pochodnego w obiekcie bazowym (Qt) » 2013-10-16 21:07:55 Witam.
Podczas analizowania kodu w bibliotece QT trafiłem na pewien problem dotyczący konstruktora. Problem ten chyba bez waszej pomocy nie zostanie rozwiązany, a jeśli tak to zajmie mi to sporo czasu.
Według Symfonii c++ istnieje pewne stwierdzenie: Obiekt jakiejś klasy - będący składnikiem innej klasy może być jedynie incjalizowany za pomocą listy inicjalizacyjnej. Nie można uruchomić takiego konstruktora z wnętrza ciała konstruktora klasy bazowej. Treść tego jest na stronie 357. Powyżej znajdziemy cały przykład do tego.
Czy ta reguła dotyczy operatora new ? Ponieważ podczas pisania przy użyciu biblioteki QT często "powołuje" się do życia nowe obiekty właśnie w ciele konstruktora klasy bazowej tym sposobem, więc to co pisze symfonia nie zgadza się z praktyką.
|
|
pekfos |
» 2013-10-16 21:16:52 Czy ta reguła dotyczy operatora new ? |
Zależy, co masz na myśli. Tu składnikiem klasy jest wskaźnik, a ten można zainicjalizować tylko na liście inicjalizacyjnej. |
|
Monika90 |
» 2013-10-16 21:18:41 Obiekt jakiejś klasy - będący składnikiem innej klasy może być jedynie incjalizowany za pomocą listy inicjalizacyjnej. Nie można uruchomić takiego konstruktora z wnętrza ciała konstruktora klasy bazowej. |
To jest prawdą (w nowszej wersji języka można też podać inicjalizator przy deklaracji składowej). Może pomyliłeś inicjalizację z przypisaniem? PS. Można też zniszcyć podobiekt w ciele konstruktora i stworzyć go na nowo za pomocą placement new, ale to nie jest normalne. |
|
CodeFun Temat założony przez niniejszego użytkownika |
» 2013-10-16 22:07:02 Tu składnikiem klasy jest wskaźnik, a ten można zainicjalizować tylko na liście inicjalizacyjnej. Składnikiem wskaźnik...czyli QPushButton * przycisk;No właśnie w tym wypadku zainicjalizowałem go w ciele konstruktora i wszystko działa. Mało tego zainicjalizowałem go w funkcji. Czyli
konstruktor::kontruktor() { funkcja(); }
void funkcja() { przycisk = new QPushButton("lalala" , this) } Chyba, że to przypisanie...
Monika90 Może pomyliłeś inicjalizację z przypisaniem?Jaka jest różnica ? x(y) inicjalizacja x = y przypisanie ? Jeśli tak to nie. Rozumiem, że przypisanie wykonać możemy poprzez funkcje składowe ?
ps. przepraszam za nie używanie pól wyszczególniających cytaty i kod. Próbowałem [quote i [code, ale coś nie zadziałało. |
|
Monika90 |
» 2013-10-16 22:44:24 przycisk = new QPushButton( "lalala", this );
Wg mnie to jest przypisanie do zmiennej przycisk. Przypisanie zawsze wygląda tak: inicjalizacja może wyglądać różnie: int x = 1; int y( 2 ); int z { 3 }; int t = int(); int u { }; int v = u;
Inicjalizacja składowej struct T { int y, z, t, u, v; T() : y(2), z{3}, t(), u{}, v(u) { } };
Inicjalizacja składowej wewnatrz klasy: struct T { int x = 1; int z { 3 }; int t = int(); int u { }; int v = u; };
|
|
CodeFun Temat założony przez niniejszego użytkownika |
» 2013-10-17 09:57:55 W takim razie jak wyglądałoby stworzenie obiektu QPushButton przy użyciu listy inicjalizacyjnej ? Konstruktor QPushButton QPushButton(const QString & text, QWidget * parent = 0)Załóżmy że mamy dwie klasy. Klasa okno i klasa przycisk. W klasie okno mamy konstruktor okna, oraz konstruktor przycisku na liście class okno { public: int x; int y; QPushButton przycisk; okno( int z, int v ) }; okno::okno( int z, int v ) : x( z ) , y( v ) , QPushButton( "lalala", this ) { } Czy tak to by miało wyglądać ? |
|
b00rt00s |
» 2013-10-18 15:09:55 Nie tak, tylko tak: class okno : public QObject { public: int x; int y; QPushButton * przycisk; okno( int z, int v ); }; okno::okno( int z, int v ) : x( z ) , y( v ) , przycisk( new QPushButton( "lalala", this ) ) { } Zwróć szczególną uwagę, że przy deklaracji przycisku dodałem znaczek *, co oznacza, że przycisk jest wskaźnikiem. Gdy go nie było wcześniej zmienna przycisk zostałaby zaalokowana na stosie z użyciem konstruktora domyślnego i używanie listy inicjalizacyjnej nie byłoby konieczne. Zwróć również uwagę na : public QObject , ponieważ rodzic musi być obiektem dziedziczącym po QObject. [EDIT] Po krótkim zastanowieniu można by było zrobić to też tak: class okno : public QObject { public: int x; int y; QPushButton przycisk; okno( int z, int v ); }; okno::okno( int z, int v ) : x( z ) , y( v ) , przycisk( "lalala", nullptr ) { } Zwróć uwagę, że jako rodzica przycisku podałem nullptr. Obiekt przycisk jest zaalokowny na stosie i podanie jako rodzica this mogłoby powodować podwójne zwalnianie pamięci, ponieważ rodzić w Qt usuwa swoje dzieci. O ile pamiętam obiekt rodzica sprawdza przed usunięciem, czy dziecko nie zostało już usunięte, więc błąd mógłby nie wystąpić, jednak generalna idea jest taka, że w Qt to rodzic zwalnia pamięć po dzieciach. |
|
CodeFun Temat założony przez niniejszego użytkownika |
» 2013-10-18 21:25:38 Właśnie odwiedziłem temat, aby oznajmić, że rozgryzłem jak wstawić obiekt QPushButton przy pomocy listy inicjalizującej. Jest to dokładnie ten sposób, który zaprezentował b00rt00s w drugim wariancie. Dodam tylko, że zamiast nullptr, użyłem this.
W związku z powyższymi odpowiedziami mam pytanie. Jaka jest różnica w obiekcie, który został stworzony w danej klasie przez new w ciele konstruktora, a wywołaniem typu NazwaKlasy Obiekt, a następnie zdefiniowanie konstruktora na liście inicjalizacyjnej konstruktora klasy bazowej. Wstępnie moja wiedza pozwala mi stwierdzić że: -powołanie do życia obiektem new jest bardziej przejrzyste w kodzie -mamy większą władzę nad obiektem, gdyż wskaźnik dostępny jest w każdym miejscu pliku - to my decydujemy kiedy likwidujemy obiekt poprzez delete... coś jeszcze ?
ps dziękuję serdecznie za wszelką udzieloną pomoc :) |
|
« 1 » 2 |