为什么女儿班级的对象调用母班级的成员函数?

时间:2019-01-02 12:56:17

标签: c++ multithreading

我想用在线程中运行任务“ work()”的方法“ execute()”创建基类“ process”。例如,当我创建派生类“产品”以及带有对象“ p”时,即使它是虚拟的,p.execute()也会运行基类的“ work()”。谁能告诉我为什么?

这是我的代码: 1-对于基类:

#include <thread>
#include <iostream>


class process 
{ 

private:

        std::thread  *th;                
public: 
    virtual void work();
    virtual void execute();

    //Delete the copy constructor
    process(const process&) = delete;

    //Delete the Assignment opeartor
    process& operator=(const process&) = delete;

    // Parameterized Constructor
    process();

    // Move Constructor
    process(process && obj);

    //Move Assignment Operator
    process & operator=(process && obj);

    //Destructor
    ~process();

}; 

// Parameterized Constructor
process::process()
{
    th!=NULL;
}

// Move Constructor
process::process(process && obj) : th(std::move(obj.th))
{
    std::cout << "Move Constructor is called" << std::endl;
}

//Move Assignment Operator
process & process::operator=(process && obj)
{
    std::cout << "Move Assignment is called" << std::endl;
    if (th->joinable())
        th->join();
    th = std::move(obj.th);
    return *this;
}


// Destructor
process::~process()
{
    if(th!=NULL){
        if (th->joinable())
          th->join();
    }
}



void process::work() 
{ 
    printf("work of base class \n");
} 


void process::execute() 
{ 
    printf("execute of base class \n");
    th=new  std::thread(&process::work, this);
} 

2-对于派生类:

class product : public process 
{ 
public: 
    void work();
};


void product::work() {
    printf("work of product class\n");
}

3个主要功能:

int main()
{
    product p;
    p.execute();

    return 0;
}

我希望得到:

execute of base class 
work of product class 

但我实际上得到了:

execute of base class 
work of base class 

1 个答案:

答案 0 :(得分:7)

您的代码具有不确定的行为,因为您加入的位置不正确。

尽管您的类在销毁时正确地加入了线程,但请确保process在线程the derived sub-object is already dead by then的整个过程中仍然有效。

因此,您可能会看到product::execute被调用,或process::execute被调用,或者猫从监视器中倒出并开始键入自己的程序。

您需要先从main内部或通过将此代码也添加到product析构函数中来销毁对象的任何

进行此更改时,我会得到预期的结果。


tl; dr:虚拟呼叫工作正常,但您的加入位置错误。


此外,您包含<iostream>但从未使用过,而是存储(并移动!)指向std::thread的指针,而不是简单地拥有std::thread和“参数化构造函数”不接受任何参数(并且没有任何用处的th!=NULL,并且不执行任何操作)。

这是上述所有内容的快速解决方案:

#include <thread>
#include <iostream>

class process 
{
private:
    std::thread th;

public:
    virtual void work();
    virtual void execute();
    void endExecution();

    ~process();
}; 

process::~process()
{
    // Just in case, but you don't want to rely on this!
    // See main() -- or do this also in ~product().
    endExecution();
}

void process::work() 
{ 
    std::cerr << "work of base class\n";
} 

void process::execute() 
{
    std::cerr << "execute of base class\n";
    th = std::thread(&process::work, this);
} 

void process::endExecution()
{
    if (th.joinable())
        th.join();
}

class product : public process 
{ 
public: 
    virtual void work() override;
};


void product::work() {
    std::cerr << "work of product class\n";
}

int main()
{
    product p;
    p.execute();
    p.endExecution();
}

live demo

更好的类设计应允许您以不太容易出错的方式进行操作。