2

我正在尝试使用以下代码在 C++ 中创建一个线程:

pthread_t mythread;
void* f (void*) = MyClass::myfunction;
pthread_create(&mythread, NULL, &f, NULL);

它不工作。知道有什么问题吗?

myfunction 的类型为:

void* MyClass::myfunction(void* argv);

返回的错误是:

error: declaration of ‘void* Class::f(void*)’ has ‘extern’ and is initialized

error: invalid pure specifier (only ‘= 0’ is allowed) before ‘::’ token

error: function ‘void* Class::f(void*)’ is initialized like a variable
4

3 回答 3

6

您声明f为函数而不是函数指针。它应该是:

void* (*f) (void*) = &MyClass::myfunction;
      ^^^^

pthread_create(&mythread, NULL, f, NULL);
                                ^ no & since it's already a pointer

这也仅在myfunction静态时才有效,因为您无法将指向成员函数的指针转换为指向函数的指针。

如果您确实需要线程在特定对象上执行非静态成员函数,那么一种方法是编写一个静态包装器,将对象作为参数:

class MyClass {
public:
    void start_thread() {
        // Pass "this" to the thread we're creating
        pthread_create(&mythread, NULL, &MyClass::thread_entry, this);
    }
private:
    static void * thread_entry(void * object) {
        // Call the member function on the object passed to the thread
        return static_cast<MyClass*>(object)->thread();
    }
    void * thread() {
        // do the interesting stuff, with access to the member variables
    }
};

当然,现在有一个标准线程库可以消除对这种舞蹈的需求:

std::thread thread(&MyClass::thread, this);
于 2012-07-04T10:42:18.353 回答
2

Pthreads 需要一个函数指针,并且对于类,您只能使用函数指针指向静态方法。

如果您想在特定对象上调用类的特定方法,则需要两个单独的数据部分:

  • 指向类方法的指针(不要将它们与函数指针混淆)
  • 指向对象的指针

这两个连接在一起可以非正式地称为委托


PThreads 是一个 C 库,要与它进行互操作,您需要一些解决方法:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void *(*start_routine)(void*),
    void *arg);

我们将把类方法包装在一个静态类方法中,以便能够将它作为参数传递start_routine,并且我们将把指向对象本身的指针传递为arg.

见代码:

struct Foo {

    // wrapper method
    static void* threadStartingPoint(void* obj) {
        return ((Foo)obj)->threadFunc();
    }

    // your target method itself
    void* threadFunc() {
        // this is where you do your logic
    }
}

这种解决方法允许您使用pthread_create(thread, attr, Foo::threadStartingPoint, someObject).


请注意,如果您有幸拥有一个支持 的现代编译器std::thread,则可以使用它而不是 pthreads 并使代码更简单 - 您只需创建一个std::function对象并将其传递给std::thread的构造函数。

于 2012-07-04T10:47:05.823 回答
1

您根本无法做您想做的事情-成员函数(除非它是静态的)需要一个要在其中调用的对象-即启动线程的进程不能只调用 MyClass::f() 因为它需要调用 something.f() - 它不知道某事是什么。

通常,通过定义一个静态成员函数来解决这个问题,该函数将对象作为参数,然后调用该对象的成员函数。

于 2012-07-04T10:42:07.323 回答