2017-03-02 3 views
0

Dieser Code kompiliert (mit g ++ (GCC) 6.3.1) und scheint zu "arbeiten". Aber ich bin sehr skeptisch, ob es gute Praxis darstellt.Ist es eine gute Übung, einen Zeiger auf eine Elementfunktion als Zeiger auf eine C-Funktion zu werfen

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 


class ThreadObj 
{ 
    public: 
    void *memberFunction(void*); 
    void startThread(void); 
    static int w; 
}; 

int ThreadObj::w = 13; 

void* ThreadObj::memberFunction(void*) 
{ 
    w = 17; 
    return 0; 
} 

void ThreadObj::startThread(void) 
{ 
    void * (*p)(void *) = *((void * (*)(void *))&ThreadObj::memberFunction); 
    pthread_t tid; 

    if (pthread_create(&tid, 0, p, this) == 0) 
    pthread_detach(tid); 
} 

int main(int argc, char *argv[]) 
{ 
    ThreadObj thr; 
    thr.startThread(); 

    return 0; 
} 

Casting einen Zeiger auf eine Elementfunktion als Zeiger auf eine C-Funktion und vorbei this als Daten (zu viel) auf die Barmherzigkeit zu verlassen scheint, wie der Compiler wählt diese zu interpretieren/kompilieren.

Dies wurde bereits behandelt, aber nicht endgültig beantwortet.

Wie kann dieses Beispiel gebrochen werden?

+5

Sie markiert diese als 'C', aber es gibt keine solche Dinge wie Mitgliederfunktionen in 'C'. – PaulMcKenzie

+2

Es ist fehlerhaft, da der Zeiger auf Funktionen verschiedener Typen nicht definiert ist. –

+2

Die Verwendung eines Funktionszeigers, der mit 'reininterpret_cast' (oder einer gleichwertigen C-Umwandlung) umgewandelt wurde, außer dem Zurücksetzen auf den Originaltyp, ist per Definition ein definiertes Verhalten. Siehe '7)' [hier] (http://en.cppreference.com/w/cpp/language/reinterpret_cast#Explanation). Hier geht es nicht so sehr um gute Praktiken, wie es in C++ nicht erlaubt ist. Was Sie * tun * können, ist eine neue statische Methode zu definieren, die einen Zeiger auf eine Instanz der Klasse akzeptiert und stattdessen einen Funktionszeiger auf diese Methode verwendet. –

Antwort

1

Die alte Art und Weise (mit dem letzten Syntax) zu gehen:

class ThreadObj 
{ 
public: 
    void memberFunction() { w = 17;} 
    void startThread() { 
     pthread_t tid; 

     if (pthread_create(&tid, 0, &Func, this) == 0) { 
      pthread_detach(tid); 
     } 
    } 
    static void* Func(void* p) { 
     auto* that = static_cast<ThreadObj*>(p); 
     that->memberFunction(); 
     return nullptr; 
    } 
private: 
    int w = 13; 
}; 

Aber in C++ 11, std::thread hat eine bessere Schnittstelle.

0

Nicht wirklich. Es ist undefiniertes Verhalten. Es ist aber ziemlich süß. Ob es funktioniert oder nicht, liegt irgendwie in der Luft. Meine Vermutung ist, dass es im Allgemeinen würde.

Der Autor des Codes nutzt die Tatsache, dass this in der Regel als erster Parameter zur Implementierung von Member-Funktionen übergeben wird.

0

Verwendung von Zeiger auf Methoden einer Klasse ist sehr nützlich und, für mich, ist eine gute Übung, weil Sie ermöglicht eine andere Art von Mustern, zum Beispiel: triggern Sie ein Ereignis über severas Klasse, die den gleichen Prototyp der Methode hat.

Beantworten Sie Ihre Frage: Es ist eine Frage von Design und wie es für Ihr Ziel nützlich sein wird.

Ich teile Ihnen einen Code, wo ich tow thread über verschiedene Methoden der gleichen Klasse, ich hoffe dir, es wird dir helfen.

https://github.com/jorgemedra/C-11-Threads/blob/master/README.md

Verwandte Themen