2013-05-18 7 views
6

In Qt, wenn ein Signal von einem temporären Objekt aufgerufen wird, so dass das Objekt gelöscht werden kann, wenn der Slot aufgerufen wird, ist es ein Fehler?Qt-Signale/Slots: Ist es ein Fehler, ein Signal von einem temporären Objekt zu senden?

Falls relevant, gibt der Code das Signal vom Konstruktor des temporären Objekts aus.

(Anmerkung: Da es keine Zeiger oder Referenzen gibt, die als Argument übergeben werden, handelt es sich also nicht um Fragezeichen oder Referenzen. Ich möchte nur wissen, ob es in seiner einfachsten Form akzeptabel ist, ein Signal zu senden . von einem temporären Objekt in Qt)

Hier ist eine verkürzte Version von meinem Code:

// My application 
class HandyApplication: public QApplication 
{ 
    Q_OBJECT 
    public: 
     explicit HandyApplication(int argc, char * argv[]); 

    signals: 

    public slots: 
     void handySlot(std::string const msg); 

}; 

// Class that will be instantiated to a temporary object 
class Handy: public QObject 
{ 
    Q_OBJECT 

    public: 

     Handy() 
     { 
      QObject::connect(this, SIGNAL(handySignal(std::string const)), 
       QCoreApplication::instance(), 
       SLOT(handySlot(std::string const))); 

      emit handySignal("My Message"); 
     } 

    signals: 

     void handySignal(std::string const msg); 

}; 

// An unrelated function that may be called in another thread 
void myFunction() 
{ 
    Handy temporaryObject; // This constructor call will emit the signal "handySignal" above 
} 

Wie Sie das temporäre Objekt sendet das Signal von seinem Konstruktor sehen können, und wird dann sofort zerstört. Daher kann der Steckplatz aufgerufen werden, nachdem das Objekt, das das Signal gesendet hat, zerstört wird.

Ist das sicher, oder ist dies ein potenzielles Problem oder ein Fehler?

Antwort

4

Was Sie angegeben haben, wäre ein direct connection vom Signal zum Steckplatz. Das bedeutet, dass Sie im Moment handySignal ausgeben, sollte es gehen und alle verbundenen Slots ausführen. Sobald alle Steckplätze (z. B. handySlot) zurückgekehrt sind, kehrt der Emitter zurück und endet mit dem Konstruktor.

Wenn Sie eine queued connection angeben würden, die verwendet würde, wenn es eine Verbindung von einem Signal in einem Thread zu einem Slot in einem anderen Thread wäre, würde die Anforderung in die auszuführende Ereignisschleife platziert.

Also würde ich sagen: Ja, es scheint in Ordnung, ein Signal von einem temporären Objekt zu emittieren, wenn Sie keine Referenzen weitergeben, die ungültig sind.

Das Beispiel scheint ein bisschen willkürlich, da ich nicht wirklich einen Punkt sehe, eine Verbindung im Konstruktor zu einem Signal herzustellen, das Sie dann aussenden, und das ist es. Sie können diesen Slot auch nur aufrufen, wenn Sie nicht erwarten, dass das Objekt in einem anderen Thread erstellt wird, den Sie nicht erwähnt haben.

Edit:

Gemäß dem Kommentar von @Kamil, sollte es, dass nicht angegeben ist, wenn ein Verbindungstyp, beachtet wird, dann ist die defailt mit einem Autoconnect sein, die die tatsächliche Art bedeutet, wird bestimmt ob der Ziel-Slot sich in einem anderen Thread befindet als der Absender. Ohne Threading würde dies einer DirectConnection gleichkommen. Mit Threading würde es eine QueuedConnection sein.

+0

Stimmt es nicht, dass der * emit * -Aufruf asynchron ist, wenn das Signal von einem anderen Thread als dem Thread gesendet wird, in dem der Slot aufgerufen wird? –

+0

@DanNissenbaum: Ya das ist, was ich gesagt habe, obwohl. Wenn es sich in einem anderen Thread befindet, wird es zu einer Verbindung in der Warteschlange.Aber selbst wenn das der Fall ist, wenn das Signal keine Objekte ausgibt, die ungültig sein könnten, dann gibt es kein Problem. Der Anruf wird in der Ziel-Thread-Ereignisschleife registriert und unabhängig vom Absender aufgerufen. – jdi

+2

Brauchen Sie * den * Anruf, um synchronisiert oder asynchron zu sein, oder ist Ihnen das egal? Im ersten Fall können Sie auch einfach die Methode aufrufen ('obj-> method (args)'); Im letzteren Fall verwenden Sie 'QMetaObject :: invokeMethod' mit' QueuedConnection', um den Aufruf zu erzwingen, wenn Sie zur Ereignisschleife zurückkehren. – peppe

1

würde ich sagen, von einem temporären Objekt emittiert ist sicher, da QObject::destroyed „wird sofort emittiert, bevor das Objekt obj wird zerstört“ - Qt docs

So vermutlich von einem temporären Objekt ausgesandten Signale würden sicher und richtig sein.