我尝试做一个工人阶级,但我得到了#34;纯粹的虚拟方法叫做#34;

时间:2018-02-09 20:34:09

标签: multithreading c++11 abstract-class

我尝试创建一个抽象类来并行化一些作品。我希望有一些东西,我可以做很多工作,而不关心它是如何完成的。但是我有一个奇怪的错误,当我运行它时,我得到了一个控制台输出"纯粹的虚拟方法叫做#34;但是当我编译它时我没有任何问题。 C ++旨在避免这种呼叫?不是吗?

这是我的抽象类:

#ifndef LIBRARIES_PARALLELISABLEPROCESS_HPP
#define LIBRARIES_PARALLELISABLEPROCESS_HPP

/* C/C++ standard libraries */
#include <string>
#include <vector>
#include <stack>
#include <thread>
#include <mutex>
#include <iostream>

/* Local inclusions */
namespace Libraries
{
    template< typename type_t >
    class ParallelisableProcess
    {
        public:

            void
            createTask (const type_t & data)
            {
                /* Adding works to the queue. */
                {
                    std::lock_guard< std::mutex > lock(m_pendingJobsAccess);

                    m_pendingJobs.emplace(data);
                }

                /* Try to start a worker if room there.
                 * Current worker ID to pass to process function. */
                auto workerID = 0;

                for ( auto & worker : m_workers )
                {
                    if ( worker.isActive )
                    {
                        workerID++;

                        continue;
                    }

                    /* Just making the process quit gently. */
                    if ( worker.process.joinable() )
                        worker.process.join();

                    std::cout << "Job given to worker #" << workerID << std::endl;

                    worker.isActive = true;
                    worker.process = std::thread(&ParallelisableProcess::process, this, workerID);

                    return;
                }

                std::cout << "All workers are busy ! " << m_pendingJobs.size() << " works pending." << std::endl;
            }

        protected:

            ParallelisableProcess (size_t workersCount)
                : m_workers(workersCount)
            {

            }

            virtual
            ~ParallelisableProcess (void)
            {
                for ( auto & worker : m_workers )
                {
                    if ( worker.process.joinable() )
                        worker.process.join();
                }
            }

            /** \brief This method takes care to pull out from the queue the next job. */
            bool
            getNextJob (type_t & data)
            {
                std::lock_guard< std::mutex > lock(m_pendingJobsAccess);

                if ( m_pendingJobs.size() > 0 )
                {
                    data = m_pendingJobs.top();

                    m_pendingJobs.pop();

                    return true;
                }

                return false;
            }

            /** \brief Task keeper. */
            void
            process (int workerID)
            {
                type_t data;

                while ( this->getNextJob(data) )
                {
                    std::cout << "Launching a real task !" << std::endl;

                    this->task(data);
                }

                /* all jobs done, telling the process is inactive. */
                m_workers[workerID].isActive = false;
            }

            /** \brief The process to build in child class. */
            virtual void task (type_t & data) = 0;

        private:

            struct Worker
            {
                bool isActive = false;
                std::thread process;
            };

            std::vector< Worker > m_workers;
            std::mutex m_pendingJobsAccess;
            std::stack< type_t > m_pendingJobs;
    };
} /* End of namespace */

#endif /* LIBRARIES_PARALLELISABLEPROCESS_HPP */

这是我的简单测试:

#include <ParallelisableProcess.hpp>

using namespace std;

using namespace Libraries;

class DumbassWorker final : public ParallelisableProcess< int >
{
    public:

        DumbassWorker (void)
            : ParallelisableProcess(4)
        {

        }

    private:

        virtual void
        task (int & data) override final
        {
            std::cout << "I'm working for " << data << " secondes.\n" << std::endl;

            std::this_thread::sleep_for(1s * data);

            std::cout << "My job is done sir !\n" << std::endl;
        }
};

int
main (int argc, const char * argv[], char * envp[])
{
    DumbassWorker worker;

    worker.createTask(5);
    worker.createTask(7);
    worker.createTask(9);
    worker.createTask(10);
    worker.createTask(15);
    worker.createTask(2);
    worker.createTask(4);
    worker.createTask(10);
    worker.createTask(5);
    worker.createTask(7);
    worker.createTask(9);
    worker.createTask(10);

    return 0;
}

我不明白为什么我要调用纯虚方法?也许我是盲人,但我无法弄清楚......

这是输出:

Job given to worker #0
Job given to worker #1
Job given to worker #2
Job given to worker #3
Launching a real task !
I'm working for 10 secondes.

Launching a real task !
I'm working for 9 secondes.

Launching a real task !
I'm working for 7 secondes.

All workers are busy ! 2 works pending.
All workers are busy ! 3 works pending.
All workers are busy ! 4 works pending.
All workers are busy ! 5 works pending.
All workers are busy ! 6 works pending.
All workers are busy ! 7 works pending.
All workers are busy ! 8 works pending.
All workers are busy ! 9 works pending.
Launching a real task !
pure virtual method called
terminate called without an active exception
Le programme s'est terminé subitement. (***Come from french dev environement)
The process was ended forcefully.

2 个答案:

答案 0 :(得分:0)

也许问题是你在基类的析构函数中加入线程,此时已经调用了孩子的析构函数。 Vptr更改为当前执行的析构函数的类。

答案 1 :(得分:0)

我得到了解决方案...... DumbassWorker析构函数首先被调用,它使DumbassWorker类的task()方法无效。所以为了让事情等待所有线程的结束,我不得不做一个&#34;等待&#34; ParallelisableProcess中的方法,我在DumbassWorker的析构函数中调用它来阻止执行,然后以正确的顺序调用析构函数。它不优雅,但它有效......

现在输出是:

java -jar boot.jar --spring.config.location=classpath:/database.properties