简体   繁体   English

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

[英]unresolved external Symbol (Constructor)

At building I get the following error: 在建筑中,我得到以下错误:

main.obj : error LNK2019: unresolved external symbol ""public: __cdecl Worker::Worker(void)" (??0Worker@@QEAA@XZ)" in function "main". main.obj:错误LNK2019:函数“ main”中未解析的外部符号““ public:__cdecl Worker :: Worker(void)”(?? 0Worker @@ QEAA @ XZ)“。

main.obj : error LNK2019: unresolved external symbol ""public: virtual __cdecl Worker::~Worker(void)" (??1Worker@@UEAA@XZ)" in function "main". main.obj:错误LNK2019:函数“ main”中未解析的外部符号““ public:虚拟__cdecl Worker ::〜Worker(void)”(?? 1Worker @@ UEAA @ XZ)”。

I cannot find the Problem. 我找不到问题。 (I also looked here ) (我也在这里看过)

main.cpp 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;
}

worker.h worker.h

#ifndef WORKER_H
#define WORKER_H


#include "jobqueue.h"
#include "job.h"
#include <mutex>
#include <thread>

using namespace std;

class Worker
{
private:
    JobQueue jobs;
    mutex mu;
    thread & workerThread;
    bool stop;

    void work();

public:
    Worker();
    virtual ~Worker();
    void addJob(Job*);
    int getJobCount();


};

#endif // WORKER_H

worker.cpp worker.cpp

#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();
}

project.pro project.pro

TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += main.cpp \
    jobqueue.cpp \
    worker.cpp

HEADERS += \
    jobqueue.h \
    worker.h \
    job.h

Deleting the Project.pro.user solves the (main-) problem, now errors are shown again 删除Project.pro.user可解决(main-)问题,现在再次显示错误

There are many mistakes in your code, as I suggested you should learn more C++ basics before this. 您的代码中有很多错误,正如我建议您在此之前应该学习更多的C ++基础知识。
As I showed the mistakes in my comments, let me answer your problem with the member function only: 当我在评论中显示错误时,让我仅使用成员函数来回答您的问题:

C++ treats functions as first class citizens, as opposed to Java (Java 8 improvements fix some issues, but it does not treat functions as first class citizens neither). 与Java相对,C ++将函数视为一等公民(Java 8改进解决了一些问题,但也没有将函数视为一等公民)。
C++ understands functions as a concept of callable entity : A callable entity is anything that could be called, ie treated as a function. C ++将函数理解为可调用实体的概念:可调用实体是可以被调用的任何事物,即被视为函数。 So a callable entity could be: 因此,可调用实体可以是:

  • A global function : Just the good old C function. 全局函数 :很好的旧C函数。 It could be defined, implemented, and called: 可以定义,实现和调用它:

     void f() {} int main() { f(); //Call to f } 
  • A member function : The classic OO member function. 成员函数 :经典的OO成员函数。 Its called within an object, and operates on its data: 它在一个对象内调用,并对其数据进行操作:

     struct foo { void f(); }; int main() { foo myfoo; myfoo.f(); //Call to foo::f } 
  • A static member function : Its a member function not linked to an object, it operates at class level, so its signature is the same as the signature of a global function (Remember this, its important as we will see later) 静态成员函数 :其成员函数未链接到对象,它在类级别运行,因此其签名与全局函数的签名相同 (请记住,其重要性,我们将在后面看到)

     struct foo { static void f(); { int main() { foo::f(); //Call to foo::f } 
  • A functor : A functor is just a class which objects are designed to work as they where functions. 函子 :函子只是一类对象被设计为在其功能所在的地方工作的类。 Thats achieved overloading the () operator: 那实现了重载()运算符:

     struct f { void operator()() const {} }; int main() { f myf; myf(); //Call to foo } 

    The standard library defines the template std::function , which is a type erased functor designed to hold any kind of callable entity: 标准库定义了模板std::function ,它是一种类型已擦除的函子,旨在容纳任何类型的可调用实体:

     #include <functional> void f() {} int main() { std::function<void()> f_wrapper; f_wrapper(); //Call to f_wrapper, which is an indirect call to f } 
  • A lambda expression: A lambda expression is just an inplace-defined anonymous functor: Lambda表达式: Lambda表达式只是就地定义的匿名函子:

     int main() { std::function<void()> lambda = [](){ std::cout << "hello!"; }; } 

    Hello! 你好!

  • A pointer to a function: C allowed the user to store functions via function pointers, just like it allows store pointers to data. 指向函数的指针: C允许用户通过函数指针存储函数,就像它允许存储指向数据的指针一样。 C++ has the same capabilities, extended for member functions too: C ++具有相同的功能,也扩展了成员功能:

     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 } 

    As we said above, static member functions have the same signature as global functions, so the syntax is exactly the same as in the example above. 如上所述,静态成员函数与全局函数具有相同的签名,因此语法与上面的示例完全相同。
    But for member functions is not the same: A member function is linked to an object, so its called within an object . 但是对于成员函数来说是不一样的:成员函数链接到对象, 因此在对象内部调用它 The syntax of a member function pointer is as follows: 成员函数指针的语法如下:

     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 } 

    A member function pointer of an specific signature has nothing to do with a pointer to a global/static function of the same signature, and cannot be convertible from/to member-pointer to non member pointer and vice-versa . 特定签名的成员函数指针与指向同一签名的全局/静态函数的指针无关,并且不能在成员指针与成员指针之间转换为非成员指针,反之亦然

    Because function pointers and member function pointers are completely separated things, we cannot treat any kind of function in an homogeneous way directly. 因为函数指针和成员函数指针是完全分开的东西,所以我们不能直接以同质方式处理任何类型的函数。 For example, we cannot make an array which holds both function pointers and member function pointers. 例如,我们不能创建一个既包含函数指针又包含成员函数指针的数组。 However, the standard library provides the function template std::bind , which allows us to bind a function to some (or all) call parameters. 但是,标准库提供了函数模板std::bind ,该模板允许我们将函数绑定到某些(或全部)调用参数。 That is, the object returned by std::bind() represents a partial (or complete) call to a callable entity . 也就是说, std::bind()返回的对象表示对可调用实体的部分(或完整)调用
    For example: 例如:

      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 } 

    As you can see, std::bind() allows us to bind certain parameters to a function, making a callable entity which represents a call to the function. 如您所见, std::bind()允许我们将某些参数绑定到函数,从而形成一个可调用实体,该实体表示对该函数的调用。 So it could be used to bind an object to a member function, making a callable entity with exactly the same form of a std::function instance initialized with any other kind of callable entity. 因此, 它可用于将对象绑定到成员函数,从而使可调用实体具有与其他任何类型的可调用实体初始化的std::function实例完全相同的形式。 That is we could use std::function to store member and non-member functions in the same way, and use it in the same way**: 那就是我们可以使用std::function以相同的方式存储成员和非成员函数,并以相同的方式使用它**:

      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(); } 

As you can see, there are many forms of callable entities. 如您所见,可调用实体有多种形式。 One important point is that someone could use C++ templates and rely on duck typing to use a callable entity passed as parameter: 重要的一点是,有人可以使用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
 } 

That's exactly what the std::thread constructor does . 这正是std::thread构造函数的作用 It just takes any kind of callable entity, a set of parameters for the call, starts a new thread, and later the callable entity is called on that new thread (Via join() or detach() . Its implementation could be something like: 它只需要任何一种可调用实体,一组调用参数,启动一个新线程,然后在该新线程上调用该可调用实体(通过join()detach() 。其实现可能类似于:

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();
}

Of course this is not a working implementation, is just an overview :p 当然,这不是可行的实现,只是一个概述:p

So now you can understand why your approach doesn't work, and what you could do to solve that. 因此,现在您可以了解为什么您的方法行不通了,以及可以采取哪些措施来解决该问题。 Specifically, use std::bind() to create a callable entity if you want to use a member function on the thread . 具体来说, 如果要在线程上使用成员函数 ,请使用std::bind()创建可调用实体

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM