web-dev-qa-db-ja.com

同じクラスの関数でクラス内にスレッドを作成する

いくつかのデータメンバーを持つクラス、およびそれらのデータメンバーにアクセスできる関数をプライベートに定義できるようにしたいと考えています。

次に、クラスのデータメンバーを操作するいくつかのスレッドを作成するパブリック関数が必要です。コードをコンパイルするのに問題があります。

ミューテックスやデータ保護について心配する必要はありません。これはテスト用のコードの例にすぎないため、これは問題にはなりません。

_class foo {
    public:
    void make_foo_func_threads();

    private:
    void foo_func();

    char private_data;
    std::vector<std::thread> some_threads;
}

void foo::foo_func() {
    while(1) {
        private_data = 'A';
    }
}

void foo::make_foo_func_thread() {
    for(...) some_threads.Push_back(std::thread(foo_func));
    for(...) some_threads.join();
}
_

コンパイラは私にエラーを与えています:

「std :: thread :: thread()への一致する呼び出しはありません」

どうやら_<unresolved overloaded function type>_からvoid (foo::*&&)'への引数1の既知の変換はありません。

ええと、ええ、私はそれがコンパイラーとは別にfoo_funcを解決する方法を理解するのに問題を抱えていることの意味がわかりません-私は思います。

コンパイラが私がやろうとしていることを理解するのにどのように役立つので、それ以上のエラーに悩まされることはありません。私が書いたコードが違法であることは間違いありません。もしそうであれば、誰かがその理由を私に説明することができます。ありがとう!

19
user3728501

foo_funcは(非static)メンバー関数であり、操作するfooのインスタンスが必要です。このインスタンスは、スレッドコンストラクターに提供する必要があります。 std :: thread :: thread のリファレンスページを参照すると、新しいスレッドで実行されるコードがわかります。関連するポイントは、fがメンバー関数へのポインターであることを参照することです。

  • fがクラスTのメンバー関数へのポインターである場合、それが呼び出されます。戻り値は無視されます。事実上、次のコードが実行されます:
    • (t1.*f)(t2, ..., tN)のタイプの場合t1は、TTへの参照、またはTから派生した型への参照です。
    • ((*t1).*f)(t2, ..., tN) さもないと。

したがって、インスタンスが必要であることは明らかです。

への変更:

for(...) some_threads.Push_back(std::thread(&foo::foo_func, this));

簡単な例

#include <iostream>
#include <thread>
#include <vector>

class foo
{
public:
    void make_foo_func_threads()
    {
        for (int i = 0; i < 5; ++i)
            some_threads.Push_back(std::thread(&foo::foo_func, this));
        for (auto& t: some_threads) t.join();
    }

private:
    void foo_func() { std::cout << "Hello\n"; }
    std::vector<std::thread> some_threads;
};

int main()
{
    foo f;
    f.make_foo_func_threads();
}
21
hmjd