Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » c++11, threads und virtuelle Funktionen

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
01.12.2016, 10:02 Uhr
PoetikBiker



Hallo zusammen,

ich möchte eine Basisklasse für Threads erstellen. Ich benutze MinGW-64.


Die Klasse sieht im wesentlichen so aus:

C++:
class ThreadBase
{
    private:
        std::thread    *m_pThread { nullptr };

    public:
        void operator()()                  { DoStartThread(); }

        void StartThread()                {m_pThread = new std::thread(*this);}

    protected:
        virtual void DoStartThread()   { cout << "ThreadBase" << endl; }





Die abgeleitete Klasse folgendermaßen:

C++:
class MyThread : public ThreadBase
{
    protected:
        virtual void DoStartThread()   { cout << "MyThread" << endl; }





jetzt instanziere ich die Klasse und starte den Thread:

C++:
int main(...)
{
    MyThread    mt;

    mt.StartThread();




Grundsätzlich funktioniert das auch, der operator() der Basisklasse wird aufgerufen.
In diesem Operator wird die Methode DoStartThread aufgerufen, die ja virtuell ist. Allerdings gibt das Prgramm "ThreadBase" aus, und nicht "MyThread", was bedeutet, das die virtuelle Methode der Basisklasse aufgerufen wird, und nicht, wie ich erwarte, die Methoder der abgeleiteten Klasse.

Kann das jemand erklären und weiß Abhilfe?

Vielen Dank und Gruß
Andreas
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
01.12.2016, 11:51 Uhr
ao

(Operator)


Ich kenne mich mit Funktoren nicht wirklich aus, aber es scheint, als ob der Funktor nur die Basisklasse zu einem _Callable macht und nicht die abgeleitete Klasse. Wenn man ThreadBase::DoStartThread pure-virtual macht (was legitim wäre mit dem Argument, dass es zweckfreie ThreadBase-Objekte nicht geben soll), dann compiliert das nicht, was mich vermuten lässt, dass der Compiler zu dem Zeitpunkt nur auf den statischen Teil der Basisklasse Zugriff hat, aber nicht auf die vtable. Probier das mal aus, vielleicht kommst du aus den Fehlermeldungen auf eine ordentliche Lösung.

Hingekriegt habe ich es mit folgender Änderung. Der Trick ist, der Basisklasse einen Pointer auf das abgeleitete Objekt zu geben und DoStartThread direkt an diesem aufzurufen. Dann landet man in MyThread::DoStartThread. Ich bin mir aber nicht sicher, ob das nicht dreckig ist.

C++:
#include <iostream>
#include <thread>

using namespace std;

class ThreadBase
{
    private:
        std::thread    *m_pThread { nullptr };

        ThreadBase * derived;        //    ein Pointer auf das abgeleitete Objekt

    public:
        void operator()()                  { derived->DoStartThread(); }    //    ()-Op ruft das abgeleitete Objekt

        void StartThread()                {m_pThread = new std::thread(*this);}

    protected:
        virtual void DoStartThread()   { cout << "ThreadBase" << endl; }

        ThreadBase (ThreadBase * derived_) : derived (derived_) {}            //    Konstruktor, um das abgeleitete Objekt bekannt zu machen
};

class MyThread : public ThreadBase
{
    protected:
        virtual void DoStartThread()   { cout << "MyThread" << endl; }

    public:
        MyThread () : ThreadBase (this) {}
};

int main()
{
    MyThread    mt;

    mt.StartThread();
}



Dieser Post wurde am 01.12.2016 um 12:33 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
01.12.2016, 14:05 Uhr
PoetikBiker




Zitat von ao:

Wenn man ThreadBase:oStartThread pure-virtual macht (was legitim wäre mit dem Argument, dass es zweckfreie ThreadBase-Objekte nicht geben soll), dann compiliert das nicht
...



Genau! Eigentlich sollte die Methode pure virtuell sein, aber das wird so nicht compiliert. Die Fehlermeldungen bringen mich allerdings nicht so richtig weiter.




Zitat von ao:

...Der Trick ist, der Basisklasse einen Pointer auf das abgeleitete Objekt zu geben und DoStartThread direkt an diesem aufzurufen. Dann landet man in MyThread:oStartThread. Ich bin mir aber nicht sicher, ob das nicht dreckig ist.



Genau so habe ich es auch gemacht, aber ja, so richtig sauber ist das meiner Meinung nach nicht.
Immerhin übergebe ich im Konstruktor der abgeleiteten Klasse einen Zeiger auf eine noch nicht vollständig konstruierte Instanz dieser Klasse.



Vielleich kann ja jemand das Problem genauer erklären! Wäre toll, zu verstehen, wo das Problem genau liegt.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
01.12.2016, 15:53 Uhr
ao

(Operator)



Zitat:
Genau! Eigentlich sollte die Methode pure virtuell sein, aber das wird so nicht compiliert. Die Fehlermeldungen bringen mich allerdings nicht so richtig weiter.


Also, eine abstrakte Basisklasse wäre eigentlich die richtige Lösung fürs Problem, und grundsätzlich scheint mir das auch zu gehen mit den Funktoren. Ich verstehe das so, dass die Fehlermeldung dadurch entsteht, dass du versuchst, die Basis by-value zu übergeben, d.h. zu kopieren, was mit abstrakten Klassen nicht geht.

Du müsstest es irgendwie schaffen, *this als Referenz oder als Pointer zu übergeben.

Vielleicht helfen die hier weiter:

http://stackoverflow.com/questions/12408158/can-a-functor-never-be-abstract-in-c
https://www.quantstart.com/articles/Function-Objects-Functors-in-C-Part-1
http://stackoverflow.com/questions/7403843/does-a-virtual-keyword-with-operator-make-sense-functors

Suchbegriffe sind "c++ abstract functor" oder "c++ functor base class".


Zitat:
Genau so habe ich es auch gemacht, aber ja, so richtig sauber ist das meiner Meinung nach nicht.
Immerhin übergebe ich im Konstruktor der abgeleiteten Klasse einen Zeiger auf eine noch nicht vollständig konstruierte Instanz dieser Klasse.

Richtig sauber ist das nicht, das stimmt. Gefährlich ist es aber nur, wenn der Basis-Konstruktor virtuelle Funktionen ruft, was grundsätzlich als böse gilt, nicht nur in diesem Fall.

Dieser Post wurde am 01.12.2016 um 16:00 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: