staging.inyokaproject.org

C++: Wie Zeiger auf Methode an einen Konstruktor übergeben?

Status: Ungelöst | Ubuntu-Version: Xubuntu 14.04 (Trusty Tahr)
Antworten |

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Ich möchte einen Zeiger auf eine Methode an einen anderen Konstruktor weiter geben. Hintergrund ist, das diese Methode von einem anderen Thread ausgeführt werden soll. Aber das gelingt mir nicht. Der Compiler erfindet immer neue Fehlermeldungen.

Angemeckert wird:

1
2
3
4
    scope = new Scope( w-(scope_w+5), h-(scope_h + 5), scope_w, scope_h );
    scope_queue = new thqueue( 10, 16 );
    scope_thread = new ScopeThread( scope_queue, &scope->shown ); // <<<<
    scope_thread->start();

typische Fehlermeldung:

cwdec.cpp:233: Fehler: ISO-C++ verbietet das Ermitteln der Adresse einer gebundenen Elementfunktion, um einen Zeiger auf Elementfunktion zu erzeugen. Stattdessen »&Scope::shown« verwenden
cwdec.cpp:233: Fehler: keine passende Funktion für Aufruf von »ScopeThread::ScopeThread(thqueue*&, int (Scope::*)(int, ...))«
cwdec.cpp:85: Anmerkung: Kandidaten sind: ScopeThread::ScopeThread(thqueue*, int (*)(int, ...))
cwdec.cpp:77: Anmerkung:                  ScopeThread::ScopeThread(const ScopeThread&)

Wenn ich versuche die gemachte Vorschläge umzusetzen, entstehen zusätzliche Fehler an andere Stelle.

Und hier sind die anderen Beteiligten:

1
2
3
4
5
6
7
8
9
class Scope : public Fl_Box {
    ...
  public:
    Scope( int x, int y, int width, int hight );
    ~Scope();
    void    draw();
    void    color( int cn, int r, int g, int b );
    int     shown( int count, ... );
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
typedef int (e_func)(int,...);

...

class ScopeThread : public Thread {
    thqueue *   thq;
    e_func *    scope_func;
    int         data[10];
 
  public:
    ScopeThread( thqueue * queue, e_func * f ) : thq( queue ), scope_func(f) {}
 
    void* run() {
        int num;
        for(;;) {
            printf( "w: " );
            thq->remove( data );
            num = data[0];
            for( int i = 0; i <= num; i++) {
                printf(" %d", data[i] ); // dummy, to be replaced!
            }
            printf( "\n" );
        }
        return NULL;
    }
};

p.s. ohne die übergebene Methode läuft das schon, gibt aber nur die Daten auf der Konsole aus.

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

Sorry für die Panikmache. Ich habe das jetzt anders gelöst. Nach folgenden Änderungen funktioniert es (erstmal):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class ScopeThread : public Thread
{
    thqueue *   thq;
    Scope *     scope_func;
    int         data[10];
 
  public:
    ScopeThread( thqueue * queue, Scope * f ) : thq( queue ), scope_func(f) {}
 
    void* run() {
        int num;
        for(;;) {
            printf( "w: " );
            thq->remove( data );
            num = data[0];
            for( int i = 0; i <= num; i++) {
                printf(" %d", data[i] );
            }
            printf( "\n" );
            scope_func->shown( data[0], data[1], data[2], data[3] );
        }
        return NULL;
    }
};
...
    scope = new Scope( w-(scope_w+5), h-(scope_h + 5), scope_w, scope_h );
    scope_queue = new thqueue( 10, 16 );
    scope_thread = new ScopeThread( scope_queue, scope );
    scope_thread->start();
...

Der eigentliche Aufruf im Thread Objekt ist jetzt zwar die Holzhammermethode, aber für einen Funktionstest ausreichend. Jetzt folgt die Feinarbeit.

Trotzdem würde mich noch interessieren, ob die ursprünglich angedachte Variante auch irgendwie möglich währe.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Dakuan schrieb:

Der eigentliche Aufruf im Thread Objekt ist jetzt zwar die Holzhammermethode, aber für einen Funktionstest ausreichend. Jetzt folgt die Feinarbeit.

Dein Problem stammt daher, dass Du für eine Memberfunktion zwei Daten übermitteln musst, nämlich den Funktionszeiger und this. Das kannst Du auch der ersten Fehlermeldung entnehmen.

Trotzdem würde mich noch interessieren, ob die ursprünglich angedachte Variante auch irgendwie möglich währe.

Das übliche und recht elegante Konzept, das ich kenne, ist der Functor - siehe insbesondere std::mem_fn (mehr Infos).

Edit: Du solltest vielleicht wieder als "ungelöst" markieren, um mehr Antworten zu bekommen.

Dakuan

(Themenstarter)
Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6532

... Das kannst Du auch der ersten Fehlermeldung entnehmen.

Eine Fehlermeldung lesen und richtig interpretieren sind 2 verschiedene Dinge 🙄

Mit "Holzhammermethode" meinte ich übrigens den umständlichen Aufruf von Scope::shown() wegen der variabel langen Parameterliste, die da nochmal kopiert wird. Jetzt wo das mit dem Thread im Prinzip funktioniert, werde ich das in einen einfachen Zeiger ändern. Der aufrufende Thread merkt davon nichts, da dazwischen ja der Ringpuffer sitzt.

Das übliche und recht elegante Konzept, das ich kenne, ist der Functor ...

Ups, da werde ich mir wohl ein neues Buch über C++ leisten müssen. In meinem alten Buch von 2009 fehlt da wohl die Hälfte.

Ok, ich setze das Thema wieder auf ungelöst um weitere Wortmeldungen anzulocken.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Dakuan schrieb:

... Das kannst Du auch der ersten Fehlermeldung entnehmen.

Eine Fehlermeldung lesen und richtig interpretieren sind 2 verschiedene Dinge 🙄

Allerdings. Ich hatte ja nicht gesagt, dass es einfach ist. 😈

Das übliche und recht elegante Konzept, das ich kenne, ist der Functor ...

Ups, da werde ich mir wohl ein neues Buch über C++ leisten müssen. In meinem alten Buch von 2009 fehlt da wohl die Hälfte.

😀

Ok, ich setze das Thema wieder auf ungelöst um weitere Wortmeldungen anzulocken.

Antworten |