C++ 未解析的外部符号(构造函数)

C++ 未解析的外部符号(构造函数),c++,lnk2019,C++,Lnk2019,在building,我得到以下错误: main.obj:错误LNK2019:未解析的外部符号“public:u cdecl Worker::Worker(void)”(??0 Worker@@QEAA@XZ)在函数“main”中 main.obj:错误LNK2019:未解析的外部符号“public:virtual\uu cdecl Worker::~Worker(void)”(??1Worker)@@UEAA@XZ)在函数“main”中 我找不到问题。(我也看了看) main.cpp #incl

在building,我得到以下错误:

main.obj:错误LNK2019:未解析的外部符号“public:u cdecl Worker::Worker(void)”(??0 Worker@@QEAA@XZ)在函数“main”中

main.obj:错误LNK2019:未解析的外部符号“public:virtual\uu cdecl Worker::~Worker(void)”(??1Worker)@@UEAA@XZ)在函数“main”中

我找不到问题。(我也看了看)

main.cpp

#include <iostream>
#include <thread>
#include "worker.h"

using namespace std;

void pause_thread(int n)
{
    std::this_thread::sleep_for (std::chrono::seconds(n));
    std::cout << "pause of " << n << " seconds ended\n";
}

int main()
{
    std::cout << "Spawning and detaching 3 threads...\n";
    std::thread (pause_thread,1).detach();
    std::thread (pause_thread,2).detach();
    std::thread (pause_thread,3).detach();
    std::cout << "Done spawning threads.\n";

    std::cout << "(the main thread will now pause for 5 seconds)\n";
    // give the detached threads time to finish (but not guaranteed!):
    pause_thread(5);

    Worker w;



    return 0;
}
#include "worker.h"

Worker::Worker(): workerThread(work), stop(false)
{
}

Worker::~Worker()
{
    workerThread.join();
}

void Worker::work(){
    while (!stop) {
        unique_lock<mutex> lock(mu, defer_lock);
        lock.lock();
            Job* job = jobs.getNextJob();
        lock.unlock();

        job->run();
        delete job;
    }
}

void Worker::addJob(Job* job){
    jobs.append(job);
}

int Worker::getJobCount(){
    unique_lock<mutex> lock(mu);
    return jobs.size();
}

<强>删除项目。PRO.U.S.解决了(主要)问题,现在错误再次显示>/P>> P>代码中有很多错误,因为我建议您在此之前应该学习更多C++基础知识。 正如我在评论中指出的错误,让我只回答您关于成员函数的问题:

C++将函数视为一等公民,而不是Java(Java 8改进解决了一些问题,但它也没有将函数视为一等公民)。
C++将函数理解为“强>可调用实体< /强>:可调用实体是可以调用的任何对象,即被视为函数。因此,可调用实体可以是:

  • 一个全局函数:只是一个好的旧C函数。它可以定义、实现和调用:

    void f() {}
    
    int main()
    {
        f(); //Call to f
    }
    
  • 成员函数:经典的OO成员函数。它在对象内调用,并对其数据进行操作:

    struct foo
    {
        void f();   
    };
    
    int main()
    {
        foo myfoo;
    
        myfoo.f(); //Call to foo::f
    }
    
  • 静态成员函数:它是一个未链接到对象的成员函数,它在类级别上运行,因此它的签名与全局函数的签名相同(记住这一点,我们将在后面看到它的重要性)

  • 一个函子:函子只是一个类,对象被设计成在它们运行函数时工作。这是通过重载()运算符实现的:

    struct f
    {
        void operator()() const
        {}
    };
    
    int main()
    {
        f myf;
    
        myf(); //Call to foo
    }
    
    标准库定义了模板
    std::function
    ,这是一个类型擦除的functor,用于保存任何类型的可调用实体:

    #include <functional>
    
    void f() {}
    
    int main()
    {
        std::function<void()> f_wrapper;
    
        f_wrapper(); //Call to f_wrapper, which is an indirect call to f
    } 
    
    如上所述,静态成员函数与全局函数具有相同的签名,因此语法与上述示例完全相同。
    但对于成员函数则不同:成员函数链接到对象,因此在对象中调用它。成员函数指针的语法如下所示:

    struct foo
    {
        voif f();
    };
    
    typedef void(foo::* pointer_to_f_type)();
    
    int main()
    {
        pointer_to_f_pointer ptr = &foo::f; //Note that the & is needed, just like in variable pointers
        foo myfoo;
    
        (myfoo.*ptr)(); //Call to the foo member function pointed by ptr (foo::f) using myfoo as object
    }
    
    特定签名的成员函数指针与指向相同签名的全局/静态函数的指针无关 签名,并且不能从/到成员指针转换为非成员指针,反之亦然

    因为函数指针和成员函数指针是完全分离的东西,我们不能处理任何类型的函数 例如,我们不能创建一个同时包含函数指针和成员函数指针的数组。 但是,标准库提供了函数模板
    std::bind
    ,它允许我们将函数绑定到一些(或所有)调用参数。 也就是说,
    std::bind()
    返回的对象表示对可调用实体的部分(或完整)调用
    例如:

     void f( int , int , int ) {}
    
     int main()
     {
         std::function<void(int,int,int)> f_wrapper = f;
    
         f(1,2,3); //Ok
         f_wrapper(1,2,3); //Ok
    
         std::function<void()> f_call = std::bind( f , 1 , 2 , 3 ); //f_call represents a partial call (Complete in this case) fo f
         f_call(); //Execute the call
    
         std::function<void(int)> partial_f_call = std::bind( f , std::placeholders::_1 , 2 , 3 );
         partial_f_call( 1 ); //Same execution as above
     } 
    
如您所见,有许多形式的可调用实体。一个重要的观点是某人可以使用C++模板,并依赖于鸭式输入来使用可调用的。 作为参数传递的实体:

 template<typename F>
 void call_function( const F& function )
 {
     function(); //function should be any kind of thing which could be called, that is, a callable entity
 } 
当然,这不是一个有效的实现,只是一个概述:p

因此,现在您可以理解为什么您的方法不起作用,以及您可以做些什么来解决这个问题。具体来说,使用
std::bind()
创建一个可调用的实体
如果要在线程上使用成员函数

是否链接文件?您必须提供所有用于链接的对象文件。您可能没有包含worker.o对象文件。作为IDE,我使用QT Creator和MSVC 2012 64位作为编译器。我将在上面发布我的项目文件。C++类的构造函数和解构主义的调用约定为:很难猜到你是怎么做到的。删除project.pro.user文件后,我得到了编译错误@MUN33626我用这个来学习C++。我从java切换,所以我在C++中没有PRO。在C++中,你必须知道java中的所有错误,编译器有更好的错误检测。顺便问一下,如果我想让线程调用Worker::work()方法,最好的方法是什么?谢谢你的工作!这个话题对我来说还是有点神秘。在编译器给了我实际的错误后,我解决了我的问题。我的解决方案仍然是Javastyle,而不是C++风格,但它现在可以工作了。我会用你的建议重构我的代码,谢谢。@ NICCOMATIK我知道在这个帖子里有太多的信息,用于C++ NeBBIE。我只是想告诉你你犯错误的原因。我建议你读一本好的C++书籍(检查这个网站的C++常见问题),然后搜索关于语言最重要的主题的好的问题/答案。
int main()
{
    std::function<void()> lambda = [](){ std::cout << "hello!"; };
}
void f() {}
void g( void(*function)() ) 
{ 
    function(); //Call to the function referenced by the pointer passed as parameter 
}

int main()
{
    g(f); //Call to g passing f as parameter. Its an indirect call to f. Note that the & is not needed
}
struct foo
{
    voif f();
};

typedef void(foo::* pointer_to_f_type)();

int main()
{
    pointer_to_f_pointer ptr = &foo::f; //Note that the & is needed, just like in variable pointers
    foo myfoo;

    (myfoo.*ptr)(); //Call to the foo member function pointed by ptr (foo::f) using myfoo as object
}
 void f( int , int , int ) {}

 int main()
 {
     std::function<void(int,int,int)> f_wrapper = f;

     f(1,2,3); //Ok
     f_wrapper(1,2,3); //Ok

     std::function<void()> f_call = std::bind( f , 1 , 2 , 3 ); //f_call represents a partial call (Complete in this case) fo f
     f_call(); //Execute the call

     std::function<void(int)> partial_f_call = std::bind( f , std::placeholders::_1 , 2 , 3 );
     partial_f_call( 1 ); //Same execution as above
 } 
 void f();

 struct foo
 {
     void f();
 };

 int main()
 {
     std::vector<std::function<void()>> functions;
     foo myfoo;

     functions.push_back( f );
     functions.push_back( std::bind( &foo::f , myfoo ) );
     functions.push_back( [](){} );
     ...

     for( const auto& function : functions )
         function();
 }
 template<typename F>
 void call_function( const F& function )
 {
     function(); //function should be any kind of thing which could be called, that is, a callable entity
 } 
template<typename F , typename... ARGS>
thread::thread( F&& function , ARGS&&... args )
{
    _thread = create_thread();

    _function = std::bind( std::forward<F>( function ) , std::forward<ARGS>( args )... ); 
}


void thread::detach()
{
    detach_thread( _thread );
    _function();
}

void thread::join()
{
    join_thread( _thread );
    _function();
}