这里我设计了snall Pipe类层次结构,问题是,我想让层次结构最小化到最终用户,所以他唯一要做的就是覆盖虚拟 功能如下:
template <typename T> class Processable{
protected:
public:
std::thread processLoop;
void myWrapper(Processable<T>* pp ){ pp->processLoopFunction();};
virtual void processLoopFunction() = 0 ;
Processable( ):processLoop(&Processable<T>::myWrapper,this,this){ processLoop.detach();};
~Processable( ){};
};
template <typename T> class Source ;
template <typename T> class Sink : public virtual Processable<T>{
// virtual void processChunk(void) = 0;
// virtual void isChunkReady(void) = 0;
protected:
public:
Source<T>* mySource;
Sink():mySource(nullptr){};
};
template <typename T> class Source : public virtual Processable<T>{
protected:
public:
lockfreequeue<T> myOutputDataBuffer;
void setSink(Sink<T>&);
virtual void processLoopFunction() = 0 ;
};
template <typename T> class Pipe : public virtual Source<T>, public virtual Sink<T>{
public:
virtual void processLoopFunction() = 0 ;
};
template <typename T> Pipe<T>& operator|(Source<T>& lhs, Pipe<T>& rhs ){ lhs.setSink(rhs) ;return rhs;};
template <typename T> Sink<T>& operator|(Source<T>& lhs, Sink<T>& rhs ){ lhs.setSink(rhs) ;return rhs;};
template <typename T> class PipeDouble: public Pipe<T>{
public:
virtual void processLoopFunction() ;
};
template <typename T> class OutputSink : public Sink<T>{
public:
virtual void processLoopFunction() ;
};
template <typename T> void Source<T>::setSink(Sink<T>& pp){
pp.mySource = this ;
};
template <typename T> class FileSource : public Source<T>{
std::ifstream myInputFile;
public:
FileSource(string filename):myInputFile(filename){};
virtual void processLoopFunction() ;
};
template <typename T> class NumberSource : public Source<T>{
public:
NumberSource(){};
virtual void processLoopFunction() ;
};
template <typename T> void OutputSink<T>::processLoopFunction(){
T tmp;
while(true){
if(this->mySource!=nullptr){
this->mySource->myOutputDataBuffer.pop(tmp);
cout << tmp << endl;
}
}
}
template <typename T> void FileSource<T>::processLoopFunction(){
T ll = 0;
while(myInputFile >> ll){
this->myOutputDataBuffer.push(ll);
}
}
template <typename T> void NumberSource<T>::processLoopFunction(){
T ll = 0 ;
while(true){
this->myOutputDataBuffer.push(ll);
ll++;
ll++;
}
}
template <typename T> void PipeDouble<T>::processLoopFunction(){
T tmp;
while(true){
if(this->mySource!=nullptr){
this->mySource->myOutputDataBuffer.pop(tmp);
tmp = tmp + tmp;
this->myOutputDataBuffer.push(tmp);
}
}
}
当然我最终还是
汤姆@奥伯伦:〜/ CPP /管道和GT; ./a.out名为terminate的纯虚方法 在没有活动异常的情况下调用Aborted
但并非总是如此(对于某些派生类,它会抛出该错误,对于其他一些人来说); 除了初始化std :: thread processLoop之外,还有一些很好的方法吗?在每个派生类中分开?
答案 0 :(得分:0)
不要使用继承。
template<typename T, typename Engine>
struct Processable {
Engine e;
std::thread myThread;
Processable( Processable&& ) = default;
Processable( Processable & ) = delete;
Processable( Processable const& ) = delete;
Processable( Processable const&& ) = delete;
Processable() = delete;
Processable& operator=(Processable const&) = delete;
Processable& operator=(Processable &&) = delete;
template<typename... Args>
explicit Processable(Args&& args):
e( std::forward<Args>(args) ),
myThread( &Engine::processLoopFunction, &e, &e )
{
myThread.detach();
}
};
现在,客户端使用(非虚拟)processLoopFunction
创建引擎类型,然后实例化Procesable<T, Engine>
,它会自动为其构建后期工作。它也完美地转发了Engine的构造函数。
但实际上,当你想要的只是一个可调用的对象时,创建一个类来做这件事似乎毫无意义。为什么不采用任意类型并在其上调用()
而不是命名processLoopFunction
方法?
同样地,创建线程对象并将它们分离也不是一个好主意,因为你只是干净关闭基本上是不可能的。