virtual Thread in class



  • theta schrieb:

    Warum?

    Weil du bereits eine virtuelle Funktion hast. Der protected-Trick macht nur wirklich Sinn, wenn das nicht der Fall ist. Diese Optimierung den Destruktor nicht virtual zu machen bringt hier so gut wie nichts, aber wenn jemand von "RunWindow" ableitet in dem Glauben da würde ja eine Polymorphe Basisklasse drunter liegen, geht alles kaputt.



  • cooky451 schrieb:

    theta schrieb:

    Warum?

    Weil du bereits eine virtuelle Funktion hast. Der protected-Trick macht nur wirklich Sinn, wenn das nicht der Fall ist. Diese Optimierung den Destruktor nicht virtual zu machen bringt hier so gut wie nichts, aber wenn jemand von "RunWindow" ableitet in dem Glauben da würde ja eine Polymorphe Basisklasse drunter liegen, geht alles kaputt.

    Naja, als Trick würde ich das nicht bezeichnen und auch nicht als Optimierung. Der Sinn ist einzig und allein, dass nicht delete auf ein Thread::Callback* aufgerufen werden kann. Wenn das benötigt werden würde, kann man den Destructor von Thread::Callback einfach public virtual machen.

    Edit

    ...aber wenn jemand von "RunWindow" ableitet in dem Glauben da würde ja eine Polymorphe Basisklasse drunter liegen, geht alles kaputt.

    Was geht kaputt?



  • theta schrieb:

    Was geht kaputt?

    RunWindow* rw = new SecondRunWindow;
    delete rw; // UB, da Destruktor nicht virtual.
    

    theta schrieb:

    Naja, als Trick würde ich das nicht bezeichnen und auch nicht als Optimierung. Der Sinn ist einzig und allein, dass nicht delete auf ein Thread::Callback* aufgerufen werden kann. Wenn das benötigt werden würde, kann man den Destructor von Thread::Callback einfach public virtual machen.

    Nein, der Sinn davon ist eher, eine Klasse komplett "non-virtual" zu halten, was hier ja gar nicht geht, weil sie schon eine virtuelle Funktion hat. Das was du beschreibst könnte man auch mit einem protected virtual Destructor erreichen. (Auch wenn das wenig sinnvoll wäre.)



  • cooky451 schrieb:

    theta schrieb:

    Was geht kaputt?

    RunWindow* rw = new SecondRunWindow;
    delete rw; // UB, da Destruktor nicht virtual.
    

    theta schrieb:

    Naja, als Trick würde ich das nicht bezeichnen und auch nicht als Optimierung. Der Sinn ist einzig und allein, dass nicht delete auf ein Thread::Callback* aufgerufen werden kann. Wenn das benötigt werden würde, kann man den Destructor von Thread::Callback einfach public virtual machen.

    Nein, der Sinn davon ist eher, eine Klasse komplett "non-virtual" zu halten, was hier ja gar nicht geht, weil sie schon eine virtuelle Funktion hat. Das was du beschreibst könnte man auch mit einem protected virtual Destructor erreichen. (Auch wenn das wenig sinnvoll wäre.)

    Was ist SecondRunWindow ?



  • class Callback
    {
    public:
        virtual DWORD run() = 0;
    protected:
        ~Callback() {}
    };
    

    Iiiiii ... 🙂
    Nachteil: Ich kann keine beliebige Funktion/Member als Thread laufen lassen, ich muss ableiten, ich muss das Interface respektieren.

    Hier eine C++03-Variante aehnlich std::thread: http://ideone.com/gQfRCV , nutzt pthread, kann aber durch die Windows-Funktionen ersetzt werden.



  • @knivil: Ja, das ist auch eine Lösung.



  • theta schrieb:

    Was ist SecondRunWindow ?

    Etwas das von RunWindow ableitet, wie ich bereits im ersten Post geschrieben hatte... (Und was soll es sonst sein, es ist implizit in RunWindow umwandelbar...)



  • cooky451 schrieb:

    theta schrieb:

    Was ist SecondRunWindow ?

    Etwas das von RunWindow ableitet, wie ich bereits im ersten Post geschrieben hatte... (Und was soll es sonst sein, es ist implizit in RunWindow umwandelbar...)

    Dann würde ich erwarten, dass RunWindow entweder einen public virtual oder einen protected non-virtual Destructor hat. Und das aus dem Grund, weil es dafür gedacht ist als Klasse in einer Basisklassen Liste zu stehen. Wenn es nicht dafür gedacht ist, dann nicht.



  • Es ist einfach eine unnötige Fehlerquelle, weil diese Optimierung hier nichts bringt. (Und jetzt schreib bitte nicht wieder es sei keine Optimierung, einen Destruktor einer Basisklasse nicht virtual zu machen ist natürlich eine.)



  • cooky451 schrieb:

    delete rw; // UB, da Destruktor nicht virtual.
    

    Nein, kein UB. Compilerfehler, da der Destruktor protected ist. Lies den gotw.



  • MFK schrieb:

    Nein, kein UB. Compilerfehler, da der Destruktor protected ist. Lies den gotw.



  • cooky451 schrieb:

    Dein Beispiel verstößt gegen die Empfehlung, dass eine Basisklasse einen public virtual oder protected nonvirtual Destruktor haben sollte. Wenn man sich an diese Empfehlung hält, erzeugt dein Beispiel kein UB.



  • MFK schrieb:

    cooky451 schrieb:

    Dein Beispiel verstößt gegen die Empfehlung, dass eine Basisklasse einen public virtual oder protected nonvirtual Destruktor haben sollte. Wenn man sich an diese Empfehlung hält, erzeugt dein Beispiel kein UB.

    👍



  • MFK schrieb:

    Dein Beispiel verstößt gegen die Empfehlung, dass eine Basisklasse einen public virtual oder protected nonvirtual Destruktor haben sollte. Wenn man sich an diese Empfehlung hält, erzeugt dein Beispiel kein UB.

    Natürlich verstößt es dagegen, aber so etwas lässt sich eben trotzdem ganz einfach und ohne Nachteil verhindern, ohne dass es auf den User abgeschoben wird, das war der Punkt des Beispiels.



  • cooky451 schrieb:

    Natürlich verstößt es dagegen, aber so etwas lässt sich eben trotzdem ganz einfach und ohne Nachteil verhindern, ohne dass es auf den User abgeschoben wird.

    D.h. jeder Klasse reflexartig einen leeren public virtual Destruktor verpassen, für den Fall, dass ein User auf die Idee kommen könnte, davon abzuleiten? Bzw. ihm durch eben diesen public virtual Destruktor auch noch zu signalisieren, dass die Klasse dafür gedacht ist? Ich weiß ja nicht.

    Aber jetzt haben wir ja final.



  • MFK schrieb:

    D.h. jeder Klasse reflexartig einen leeren public virtual Destruktor verpassen, für den Fall, dass ein User auf die Idee kommen könnte, davon abzuleiten? Bzw. ihm durch eben diesen public virtual Destruktor auch noch zu signalisieren, dass die Klasse dafür gedacht ist? Ich weiß ja nicht.

    Nein, aber eine Klasse von der man ableiten soll (dafür ist Callback ja gedacht), und die außerdem bereits eine virtuelle Funktion hat, sollte einen virtuellen Destruktor haben.


Anmelden zum Antworten