0

I have a question related with C++ and threads. I am more familiar with Java than C++ and this error is confusing me.

Imagine that in x.h file I have a class such as:

class A{

    public A();

    public virtual void* func(void*);

    public virtual void func2();

    public virtual void func3();

};

In x.cpp file I want to do that:

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...

}

The problem is it hangs with the following error:

"error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function."

What should I do to fix this?

Thanks.

4

4 に答える 4

3

This is a lousy error message, but fundamentally what it's trying to tell you is that you can't form a function pointer from an instance method (I'm not sure what Java's terminology here is). This is because to call an instance method you need both the address of the actual code and the address of an object to be this, and a regular function pointer only stores the former.

What you need here is a static wrapper method which matches pthread_create's expectations of the thread start routine. You pass this as the fourth argument to pthread_create, and the wrapper converts its argument back to an object pointer and invokes func. This type of wrapper is commonly known as a "thunk", since it adapts one calling convention to another.

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));
    // ...
}

The casts are unavoidable.

于 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

次のいずれかを使用します。

  • boost :: thread
  • C ++ 11
  • 他のいくつかのC++ライブラリスレッド(それらの多く)
  • クラスに静的メソッドを追加し、そのアドレスを、呼び出したいクラスインスタンス(ポインタ/参照)とclass::*メソッドのペアにpthread_create提供されたユーザーに渡します。void*次に、静的関数で、パラメータから取得したインスタンスとメソッドアドレスを使用して目的のメソッドを呼び出すだけです。
于 2012-12-05T14:44:00.317 に答える
0

In pthread_create(&t1, NULL, &func, NULL); you try to take the address of a member function. There are two issues with that

  1. The correct form is

    &A::func

    this is what the compiler tries to tell you.

  2. pthread_create wants a pointer to function, not a pointer to a non-static member function. What you can do instead is, creating a static member function and passing the address of this static member function as an argument to pthread_create.

Example:

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

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