在建设中,我收到以下错误:
main.obj:错误LNK2019:未解析的外部符号“”public:__ cdecl Worker :: Worker(void)“(?? 0Worker @@ QEAA @ XZ)”在函数“main”中 . main.obj:错误LNK2019:未解析的外部符号“”public:virtual __cdecl Worker :: ~Worker(void)“(?? 1Worker @@ UEAA @ XZ)”在函数“main”中 .
我找不到问题 . (我也看了here)
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
#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
#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
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
1 回答
您的代码中存在许多错误,因为我建议您在此之前应该了解更多C基础知识 .
当我在评论中显示错误时,让我用成员函数回答你的问题:
C将函数视为一等公民,而不是Java(Java 8改进修复了一些问题,但它并未将函数视为一等公民) .
C将函数理解为 callable entity 的概念:可调用实体是可以被调用的任何东西,即被视为函数 . 所以可调用的实体可以是:
标准库定义了模板
std::function
,它是一种类型擦除函子,用于存放任何类型的可调用实体:如上所述,静态成员函数与全局函数具有相同的签名,因此语法与上例中的完全相同 .
但是对于成员函数是不一样的:成员函数链接到一个对象 so its called within an object . 成员函数指针的语法如下:
特定签名 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 的成员函数指针 .
因为函数指针和成员函数指针是完全分离的东西,例如,我们不能创建一个包含函数指针和成员函数指针的数组 . 但是,标准库提供了函数模板
std::bind
,它允许我们将函数绑定到某些(或所有)调用参数 . 也就是说,std::bind()
返回的对象代表 a partial (or complete) call to a callable entity .例如:
如您所见,
std::bind()
允许我们将某些参数绑定到函数,从而形成一个可调用的实体,该实体表示对函数的调用 . 那么 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
以相同的方式存储成员函数和非成员函数,并以相同的方式使用它**:如您所见,有许多形式的可调用实体 . 一个重点是有人可以使用C模板并依赖duck typing来使用作为参数传递的可调用实体:
That's exactly what the std::thread constructor does . 它只需要任何类型的可调用实体,一组调用参数,启动一个新线程,然后在该新线程上调用可调用实体(通过
join()
或detach()
. 它的实现可能类似于:当然这不是一个有效的实现,只是一个概述:p
所以现在你可以理解为什么你的方法不起作用,以及你可以做些什么来解决这个问题 . 具体来说, use std::bind() to create a callable entity if you want to use a member function on the thread .