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

Konstruktor obiektu pochodnego w obiekcie bazowym (Qt)

Ostatnio zmodyfikowano 2013-10-22 17:15
Autor Wiadomość
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ą.


P-93844
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.
P-93845
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.
P-93846
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.
P-93852
Monika90
» 2013-10-16 22:44:24
C/C++
przycisk = new QPushButton( "lalala", this );
Wg mnie to jest przypisanie do zmiennej przycisk.

Przypisanie zawsze wygląda tak:
C/C++
wyrazenie1 = wyrazenie2

inicjalizacja może wyglądać różnie:
C/C++
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:
C/C++
struct T {
    int x = 1;
    int z { 3 };
    int t = int();
    int u { };
    int v = u;
};
P-93854
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

C/C++
class okno
{
public:
    int x; //wymiary okna
    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ć ?
P-93859
b00rt00s
» 2013-10-18 15:09:55
Nie tak, tylko tak:
C/C++
class okno
    : public QObject
{
public:
    int x; //wymiary okna
    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:

C/C++
class okno
    : public QObject
{
public:
    int x; //wymiary okna
    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.
P-93945
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 :)
P-93980
« 1 » 2
  Strona 1 z 2 Następna strona