首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在不使用模板的情况下使用基类的派生方法运行线程

在不使用模板的情况下使用基类的派生方法运行线程
EN

Stack Overflow用户
提问于 2020-02-14 22:03:04
回答 4查看 169关注 0票数 0

我想实现非模板化的类,就像评论的那样。未注释的类将导致编译错误error: invalid use of non-static member function 'virtual void BaseThread::worker()

代码语言:javascript
复制
#include <iostream>
#include <thread>

/*
class BaseThread
{
public:
    void start()
    {
// error: invalid use of non-static member function 'virtual void BaseThread::worker()'
        thread_ = std::thread(worker);
    }

private:
    virtual void worker() = 0;

    std::thread thread_;
};
*/

template <typename Derived>
class BaseThread
{
public:
    void start()
    {
        thread_ = std::thread(Derived::worker);
    }

private:
    virtual void worker() = 0;

    std::thread thread_;
};

class DerivedThread : public BaseThread<DerivedThread>
{ 
private:
    void worker()
    {
        std::cout << "Derived\n";
    }
};

int main()
{
    DerivedThread dt;
}
EN

回答 4

Stack Overflow用户

发布于 2020-02-14 22:18:49

要点很简单:您将一个成员函数传递给一个线程对象,而不是一个可以调用该函数的对象。

模板似乎只解决了这个问题,因为您没有实例化它。一旦你这样做了,同样的问题就会再次出现。

您可以通过将实例作为参数传递来解决此问题:

代码语言:javascript
复制
thread_ = std::thread(&BaseThread::worker, this);

此外,您必须通过适当的运算符和类范围解析来获取成员函数指针。

附注:当你有一个虚拟函数时,你应该考虑添加一个虚拟析构函数,否则通过指向基类的指针删除派生类将会失败。

也不要忘了在析构函数中加入线程(或者你觉得合适的任何地方)。

票数 3
EN

Stack Overflow用户

发布于 2020-02-14 22:18:37

为什么这个不能编译?重点是你根本没有得到正确的语法,仅此而已。不能在没有对象的情况下调用成员函数。将它们传递给std::thread的一种简单方法如下:

代码语言:javascript
复制
std::thread th{&ThreadBase::worker, this}

然而,您选择了一个不幸的抽象,那就是首先创建一个“线程”类,这需要您从派生。不要这样做,因为它混合了两个关注点,即被调用的代码和线程。在某种程度上,这类似于创建一个文件基类,从这个基类派生出不同的文件格式。这种有缺陷的方法的标志是,在这两种情况下,线程或文件的实例都不是线程或文件!想想看,std::thread的实例不是线程,std::fstream的实例也不是文件。相反,这些对象是可用于与线程或文件交互的对象,类似于数据库客户端用于与数据库交互的方式。

总之,不要编写从BaseThread派生的类,只需编写执行某些操作的类即可。不要让这个类担心它的代码是否在线程中被调用。如果你想这样做,只需使用你已经在幕后做过的std::thread即可。

票数 1
EN

Stack Overflow用户

发布于 2020-02-14 22:23:42

更简单和非模板化的实现可以是这样的。

代码语言:javascript
复制
#include <thread>
#include <iostream>
#include <functional>

class BaseThread
{
public:
    virtual ~BaseThread() { thread_.join(); }
    void start()
    {
        thread_ = std::thread( &BaseThread::worker , this );        
    }

protected:

    virtual void worker() = 0;

private:

    std::thread thread_;
};

class DerivedThread : public BaseThread
{

protected:

    void worker() override
    {
        std::cout << "Derived\n";
    }
};

int main()
{

    DerivedThread dt;
    DerivedThread dt2;

    dt.start();
    dt2.start();

    std::this_thread::sleep_for( std::chrono::seconds { 5 } );
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60227836

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档