被称为纯虚方法

jak*_*gut 10 c++ inheritance multithreading pure-virtual

编辑:已解决

我现在正在开发一个多线程项目,我有一个基础工作者类,具有从中继承的不同工作类.在运行时,工作类成为线程,然后根据需要执行工作.

现在,我有一个我写过的Director,它应该维护一个指向所有worker的指针数组,以便它可以从中检索信息,以及稍后修改它们中的变量.

我通过创建指向基类指针的指针来完成此操作:

baseWorkerClass** workerPtrArray;
Run Code Online (Sandbox Code Playgroud)

然后在Director的构造函数中,我动态地为基础worker类分配一个指针数组:

workerPtrArray = new baseWorkerClass*[numWorkers];
Run Code Online (Sandbox Code Playgroud)

在每个工作线程的构造函数中,worker调用director中的一个函数,该函数用于将该worker的指针存储在数组中.

以下是导演存储指针的方式:

Director::manageWorker(baseWorkerClass* worker)
{
    workerPtrArray[worker->getThreadID()] = worker;
}
Run Code Online (Sandbox Code Playgroud)

以下是工人变体的示例.每个worker都继承自基类worker类,而base worker类包含纯虚函数,这些函数应该存在于所有worker变量中,以及一些在所有worker之间共享的变量.

class workerVariant : protected baseWorkerClass
{
    public:

    workerVariant(int id)
    : id(id)
    {
        Director::manageWorker(this);
    }

    ~workerVariant()
    {
    }

    int getThreadID()
    {
        return id;
    }

    int getSomeVariable()
    {
        return someVariable;
    }

    protected:

    int id;
    int someVariable
};
Run Code Online (Sandbox Code Playgroud)

然后baseWorkerClass看起来像这样:

class baseWorkerClass
{
public:

    baseWorkerClass()
    {
    }

    ~baseWorkerClass()
    {
    }

    virtual int getThreadID() = 0;
    virtual int getSomeVariable() = 0;
};
Run Code Online (Sandbox Code Playgroud)

在每个worker变量完成初始化之后,我应该得到一个指向baseWorkerClass对象的指针数组.这意味着我应该能够,例如,使用其ID作为数组的索引来获取某个工作中给定变量的值,如下所示:

workerPtrArray[5]->getSomeVariable(); // Get someVariable from worker thread 5
Run Code Online (Sandbox Code Playgroud)

问题是这段代码导致Windows可执行文件崩溃,没有任何解释原因,在Linux中,它说:

名为
terminate的纯虚方法在没有活动异常的情况下被调用
Aborted

我可以发誓我曾经在某个时候工作过,所以我很困惑我搞砸了什么.


有问题的实际未修改代码:

Worker变量头:http://pastebin.com/f4bb055c8
Worker变量源文件:http://pastebin.com/f25c9e9e3

基础工作者类头:http://pastebin.com/f2effac5
基本工作者类源文件:http://pastebin.com/f3506095b

主管标题:http://pastebin.com/f6ab1767a
导演源文件:http://pastebin.com/f5f460aae


编辑:额外的信息,在manageWorker函数中,我可以从指针"worker"调用任何纯虚函数,它工作得很好.在manageWorker函数之外,当我尝试使用指针数组时,它会失败.

编辑:现在我考虑一下,线程的入口点是operator().Director线程在worker之前创建,这可能意味着重载的括号运算符在被子类覆盖之前调用纯虚函数.我在调查这个.

Joh*_*lla 12

问题似乎Director::manageWorker是在workerVariant实例的构造函数中调用:

Director::manageWorker(baseWorkerClass* worker) {
    workerPtrArray[worker->getThreadID()] = worker;
}
Run Code Online (Sandbox Code Playgroud)

大概getThreadID()不是一个纯粹的虚函数,或者你会(希望!)得到一个关于不覆盖它的编译器错误workerVariant.但是getThreadID()可能会调用你应该覆盖的其他函数,但是在抽象类中调用它们.你应该仔细检查一下这个定义,getThreadID()以确保在正确初始化之前你没有做任何不利于子类的事情.

更好的解决方案可能是将这种多阶段初始化分离为单独的方法,或设计Director并使baseWorkerClass它们没有这种初始化时间相互依赖性.

  • 当一个对象正在构建时(执行构造函数时),虚函数机制永远不会调用从对象类型派生的类的虚函数.这是因为派生类的构造函数尚未执行.因此,从构造函数调用派生类的方法将不起作用.解决这个问题的方法是两阶段构造,最好隐藏在包装器对象后面.(同样适用于销毁,BTW.) (14认同)