Ich bin neu in Qt und lese verschiedene Qt-Projekte, um die Grundlagen zu bekommen. Beim Durchsuchen der verschiedenen Klassen werden immer Zeiger auf QWidget verwendet.
Beispiel:
%Vor%Gibt es einen Grund dafür, Zeiger für 'QPushButton' * 'QHBoxLayout' * usw. zu verwenden? Können wir nur Werte verwenden, damit wir uns nicht mit 'new' und 'delete' beschäftigen müssen? Nun, ich weiß, wir können, aber ist es ein guter Weg, es zu tun?
z. B.
%Vor%BEARBEITEN:
Alle Antworten scheinen auf die Hierarchie zwischen Qt-Klassen hinzuweisen. Es ist ein guter Grund für mich und ich zweifle nicht an dem Punkt, aber sagen wir, dass es keine Verbindung zwischen den Widgets meiner Klasse gibt (* m_stopButton * und * m_playButton *).
Ich kann sie in diesem Fall sicher als Werte deklarieren, oder? Wenn die Klasse gelöscht wird, werden die Mitglieder auch gelöscht, also Zeiger oder nicht, wir werden das gleiche Verhalten haben.
Sie möchten die Zeiger verwenden, wenn Sie die volle Kontrolle über die Lebensdauer des Objekts haben möchten. Zum Beispiel
Wenn Sie ein Klassenmitglied zu einem Zeitpunkt erstellen möchten, nachdem die Initialisierungsliste im Konstruktor verarbeitet wurde.
Wenn Sie ein Klassenmitglied zu einem Zeitpunkt zerstören wollen, bevor der vom Compiler erzeugte Destruktor-Epilog ausgeführt wird.
Es ist völlig ungefährlich, die Zeiger nicht zu verwenden, wenn Sie mit dem Compiler fertig sind, der die Objektinstanzen für Sie konstruiert und zerstört.
Unverarbeitete Zeiger erweisen sich als fehleranfällig, wenn sie die Ressource besitzen, auf die sie verweisen: Es ist ein Fehler zu vergessen, die eigene Ressource zu löschen, die Ressource mehrmals zu löschen oder eine zu dereferenzieren bereits gelöschte Ressource.
Die Verwendung von unformatierten Zeigern (im Gegensatz zu intelligenten Zeigern), die die Ressource nicht besitzen - wenn die Ressource von einer anderen Person freigegeben wird - kann immer noch ein Fall einer vorzeitigen Optimierung sein. Die Verwendung von unformatierten Zeigern neigt dazu, "kleine" Codeänderungen in Ressourcenlecks umzuwandeln:
%Vor% Die Smartpointer - C ++ 11's std::unique_ptr
, Qt 4.6's QScopedPointer
- garantieren, dass die Löschung immer geschieht und dass der Zugriff auf eine gelöschte Ressource einer Nullzeiger-Dereferenz entspricht und somit nominal abgefangen und signalisiert wird von der Prozessorhardware.
In C ++ ist die Reihenfolge der Konstruktion und Zerstörung von Klassenmitgliedern und automatischen Variablen festgelegt . In den folgenden Beispielen lautet die Reihenfolge der Konstruktion immer a
, dann b
und die Reihenfolge der Vernichtung ist immer b
und dann a
. Das ist sehr wichtig .
Somit ist der folgende Code gültig und verhält sich korrekt unter mindestens Qt 3, Qt 4 und Qt 5, sofern nicht anders angegeben.
%Vor% In allen Fällen lautet die Konstruktionsreihenfolge: c, a, b
; Die Reihenfolge der Zerstörung lautet: b, a, c
.
Qt ist im Grunde wie C ++ anno 1996 oder so konzipiert (oder sehr Java-esque, wenn Sie so wollen). Viele Hinweise, viele Vererbungen.
Ein Grund, warum sie häufig Zeiger verwenden, ist natürlich, dass die Vererbung praktisch überall ist, und es vermeidet alle mit dem Schneiden verbundenen Probleme.
Ein weiterer Grund ist, dass Qt eine starke Konvention hat, dass die Speicherverwaltung so gehandhabt wird, dass jedem Objekt ein Elternteil zugewiesen wird. Wenn der Elternteil zerstört wird, ruft er delete
für seine Kinder auf.
Wenn Sie Ihr Objekt als lokales Objekt anstelle eines Zeigers für etwas deklarieren, das mit new
zugeordnet ist, dann müssen Sie vorsichtig sein, ob Sie ihm kein übergeordnetes Element zuweisen oder auf andere Weise sicherstellen, dass es außerhalb des Bereichs vor dem übergeordneten Objekt liegt um sicherzustellen, dass delete
niemals aufgerufen wird.
Ja, es gibt einen Grund. Alle Unterklassen von QObject
können mit dem Attribut parent
in eine Hierarchie gestellt werden. Es ist sehr nützlich, weil es ermöglicht, dass eine Aktion für QObject
an alle untergeordneten Klassen weitergegeben wird. Eine dieser Aktionen ist show
oder hide
für Widgets, ein anderes ist die Objektzerstörung.
Wenn Sie QObject
löschen (auch Qwidget
), werden alle seine Kinder gelöscht. , wie das Dokument sagt
Warnung: Alle untergeordneten Objekte werden gelöscht. Wenn eines dieser Objekte aktiviert ist der Stapel oder global, früher oder später wird Ihr Programm abstürzen
Außerdem können Sie Objekte in andere Threads verschieben. Um dies zu tun, müssen diese Objekte in einem Speicherbereich sein, der für alle Threads in einem Prozess verfügbar ist. Der Stack ist für einen einzelnen Thread, also nicht geeignet.
In einer reinen Sprachperspektive haben Sie nur den Konstruktor
%Vor% Wenn Sie einen Wert für das übergeordnete Element angeben, das sich von NULL
unterscheidet, sollte dieser Wert eine höhere Lebensdauer haben als das zu erstellende Objekt. Andernfalls könnte eine ungültige Referenz verwendet werden.
Im Grunde hatten sie verschiedene Mechanismen, die sie einsetzen wollten, und mit verschiedenen Einschränkungen (einschließlich Rückwärtskompatibilität ) ist es diejenige, die sie gewählt haben.
Der Grund ist historisch. Wenn Sie in älteren Qt-Versionen das übergeordnete Widget an die Konstruktoren der Elementwidgets übergeben, ruft das übergeordnete QWidget::~QWidget
delete
für die untergeordneten Widgets auf.
In aktuellen Qt-Versionen wurde eine Überprüfung hinzugefügt, um zu sehen, ob das untergeordnete Widget bereits gelöscht wurde, was bedeutet, dass Sie nun normale Mitglieder daraus machen können.