类A是基本类,B是A的继承类,q是unique_ptr(class A)类型的队列。 下面是我的代码:
class A{
public:
virtual void doSomeWork(){
std::cout<< "doSomeBasicWork"<<std::endl;
}
};
class B:public A{
public:
void doSomeWork(){
std::cout<< "doSomeSpecificWork"<<std::endl;
}
};
int main(){
std::unique_ptr<A> p=std::make_unique<B>();
std::queue<std::unique_ptr<A>> q;
q.push(std::move(p));
auto x=std::move(q.front());
x->doSomeWork();//print “doSomeSpecificWork”
}
所以你可以看到,在单线程中一切都很好,但是当我在多线程下重写这个:
#include <stdio.h>
#include <time.h>
#include <iomanip>
#include <windows.h>
#include<thread>
#include <iostream>
#include <queue>
class A{
public:
virtual void doSomeWork(){
std::cout<< "doSomeBasicWork"<<std::endl;
}
};
class B:public A{
public:
void doSomeWork(){
std::cout<< "doSomeSpecificWork"<<std::endl;
}
};
void producer(std::queue<std::unique_ptr<A>>& q){
Sleep(1000);
auto a=std::make_unique<A>();
q.push(std::move(a));
}
void consumer(std::queue<std::unique_ptr<A>>& q){
Sleep(1500);
auto p=std::move(q.front());
q.pop();
p->doSomeWork();
}
int main(){
auto q=std::queue<std::unique_ptr<A>>();
auto t1=std::thread(consumer,std::ref(q));
auto t2=std::thread(producer,std::ref(q));
t1.join();
t2.join();
}
输出将是“DoSomeBasicWork”,多态性消失了。 我该怎么做才能解决这个问题?
正如所指出的,根本原因是一个打字错误。 但是,我强烈怀疑输出会是一样的。 这是因为您使用了std::make_unique
。 这将创建一个新实例,但其基类型为a
。 你可以在这里读到这一点,重要的部分是:
构造类型T的对象并将其包装在std::unique_ptr中。
为了解决这个问题,您必须模板化您的函数,向std::make_unique
提供具体类型
像这样的东西:
template<class TType>
void producer(std::queue<std::unique_ptr<A>>& q){
Sleep(1000);
auto a=std::make_unique<TType>();
q.push(std::move(a));
}
而且,正如其他人所指出的,你需要使用某种锁定机制,否则你会得到竞态条件。 看看这里和这里。