0

我有一个与 C++ 和线程相关的问题。我比 C++ 更熟悉 Java,这个错误让我很困惑。

想象一下,在 xh 文件中,我有一个类,例如:

class A{

    public A();

    public virtual void* func(void*);

    public virtual void func2();

    public virtual void func3();

};

在 x.cpp 文件中,我想这样做:

void* A::func(void*) {

    while(....)
        func2();

    return NULL;
}

void A::func2() {

    ...some stuff there...

}

void A::func3() {

    pthread_t t1;

    pthread_create(&t1, NULL, &A::func, NULL);

    void* result;

    pthread_join(t1,&result);

    ...some other stuff...

}

问题是它挂起并出现以下错误:

“错误:ISO C++ 禁止使用不合格或带括号的非静态成员函数的地址来形成指向成员函数的指针。”

我应该怎么做才能解决这个问题?

谢谢。

4

4 回答 4

3

这是一条糟糕的错误消息,但从根本上说,它试图告诉您的是,您不能从实例方法中形成函数指针(我不确定这里的 Java 术语是什么)。这是因为要调用实例方法,您需要实际代码的地址和对象的地址this,而常规函数指针只存储前者。

您在这里需要的是一个static包装方法,它与pthread_create线程启动例程的期望相匹配。您将this作为第四个参数传递给pthread_create,包装器将其参数转换回对象指针并调用func。这种类型的包装器通常被称为“ thunk ”,因为它使一种调用约定适应另一种。

class A {
    // ...
    static void* thread_start_thunk(void* self);
};

void*
A::thread_start_thunk(void* self)
{
    return static_cast<A*>(self)->func();
}

// ...

void
A::func3()
{
    // ....
    pthread_create(&t1, 0, &A::thread_start_thunk, static_cast<void*>(this));
    // ...
}

演员表是不可避免的。

于 2012-12-05T14:47:35.083 回答
2

您不能只将指向方法的指针传递给线程。单独的方法指针没有任何意义,因为它不知道它属于哪个实例。如果您需要在不同的线程中调用实例方法,请向该类添加一个私有静态方法并将其地址以及指向该实例的指针作为参数传递给该线程。

该静态方法可能看起来像这样:

class A
{
    public: virtual void threadMethod();

    public:
        static void staticThreadMethod(void* instanceObj)
        {
            ((A*)instanceObj)->threadMethod();
        }
};

我没有测试该代码,它显然不会检查错误,但这是我通常的做法。

于 2012-12-05T14:44:19.563 回答
1

使用以下之一:

  • 提升::线程
  • C++11
  • 其他一些 C++ 库线程(很多)
  • 向您的类添加一个静态方法,然后将其地址传递给pthread_create提供void*给您的类实例(指针/引用)和您要调用的类::*方法对的用户。然后在静态函数中,只需使用从参数获取的实例和方法地址调用所需的方法
于 2012-12-05T14:44:00.317 回答
0

pthread_create(&t1, NULL, &func, NULL);您尝试获取成员函数的地址。有两个问题

  1. 正确的形式是

    &A::func

    这就是编译器试图告诉你的。

  2. pthread_create想要一个指向函数的指针,而不是指向非静态成员函数的指针。相反,您可以做的是创建一个静态成员函数并将该静态成员函数的地址作为参数传递给pthread_create.

例子:

class A {
public:
    static void *func(void *);
};

pthread_t t1;
pthread_create(&t1, NULL, &A::func, NULL);
于 2012-12-05T15:09:31.040 回答