Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 子类中的虚拟函数调用父函数一次_C++_Multithreading_Inheritance - Fatal编程技术网

C++ 子类中的虚拟函数调用父函数一次

C++ 子类中的虚拟函数调用父函数一次,c++,multithreading,inheritance,C++,Multithreading,Inheritance,这个问题似乎与线程和快速运行程序有关。我有两个类,ThreadParent和ThreadChild,其中一个从另一个继承ThreadParent创建一个线程并运行函数func,该函数声明为静态以避免指针问题。但是,我确实希望继承的类,如ThreadChild决定线程究竟执行什么操作func调用虚拟函数do 但是,当创建ThreadChild对象并立即在开始时运行线程调用ThreadParent::Do一次时,以下所有调用都是ThreadChild::Do。有趣的是,当我在调用Do之前稍等片刻时,

这个问题似乎与线程和快速运行程序有关。我有两个类,
ThreadParent
ThreadChild
,其中一个从另一个继承
ThreadParent
创建一个线程并运行函数
func
,该函数声明为静态以避免指针问题。但是,我确实希望继承的类,如
ThreadChild
决定线程究竟执行什么操作
func
调用虚拟函数
do

但是,当创建
ThreadChild
对象并立即在开始时运行线程调用
ThreadParent::Do
一次时,以下所有调用都是
ThreadChild::Do
。有趣的是,当我在调用
Do
之前稍等片刻时,它并没有发生

还有比等待更好的解决方案吗?更重要的是,为什么会发生这种情况


下面是一个小但完整的示例。它创建一个
ThreadChild
对象,该对象每200ms执行一次
Do
。程序在1s后结束(等待回车键)

#包括
#包括
#包括
//父类
类ThreadParent{
受保护的:
bool _loopThread;//将此设置为false将结束线程
std::thread _thread;//线程
公众:
//基本构造
线程父级(线程父级*子级)
:_loopThread(true),
_线程(func,child,&_loopThread){}
//停止线程并等待它完成
void StopThread(){
_loopThread=false;
_thread.join();
}
受保护的:
//线程将运行的函数(由于指针问题而处于静态)
静态void func(线程父对象*子对象,布尔对象*循环线程){
//Sleep(10);//Do();//每隔200ms调用一次Do
睡眠(200);
}
}
//重复调用直到_loopThread设置为false的函数
虚拟void Do(){

std::cout在构造过程中,基类子对象在派生类之前构造。在基类主体内,动态类型实际上是基类的类型,因此动态函数分派(虚拟函数调用)将调用基类的相应函数。因此,根据时间的不同,您将看到任何一个函数被调用

为了解决这个问题,只需在构造完成后调用的第二个初始化函数中显式启动线程


顺便说一句:
static
函数是一个红鲱鱼,你不能避免任何错误。另外,创建线程层次结构通常是一个坏主意。相反,你的类实例代表任务或作业,这些任务或作业可能在单独的线程中执行,也可能不在单独的线程中执行。将这些对象紧密耦合到线程可能是个坏主意。此外,你传递po的方式基类构造函数的inter似乎很脆弱,因为它创建了一个本来不应该存在的依赖项。

当派生类实例化时,首先调用基类构造函数,然后将vtable指针
vptr
初始化为基类vtable,其中包含指向
ThreadParent::Do的指针。仅当派生类构造函数运行时,vtable指针
vptr
被重写(指向)到dervied类vtable,该类包含指向
ThreadChild::Do
的指针

因此,从基类构造函数调用虚方法将始终调用基类实现,而不是派生类覆盖的方法

#include <iostream>
#include <windows.h>
#include <thread>

// The parent class
class ThreadParent {
protected:
    bool _loopThread; //setting this to false should end the thread
    std::thread _thread; //the thread

public:
    // Basic constructor
    ThreadParent(ThreadParent* child)
        : _loopThread(true),
        _thread(func, child, &_loopThread) {}

    // Stops the thread and waits for it to finish
    void StopThread() {
        _loopThread = false;
        _thread.join();
    }

protected:
    // The function the thread will be running (static because of pointer issues)
    static void func(ThreadParent* child, bool* loopThread) {
        //Sleep(10); //<- uncomment to solve the problem?
        while (*loopThread) {
            child->Do(); // Do is called every 200ms
            Sleep(200);
        }
    }
    // The function which is called repeatedly until _loopThread is set to false
    virtual void Do() {
        std::cout << "Parent call\n";
    }
};

// The child class
class ThreadChild : public ThreadParent {
public:
    // Basic constructor
    ThreadChild()
        : ThreadParent(this) {}

protected:
    // Redefines Do() with another message
    void Do() {
        std::cout << "Child call\n";
    }
};

// The program
int main() {
    ThreadChild thread;  // Create and run the thread
    Sleep(1000);         // Run the thread for 1s
    thread.StopThread(); // End it
    std::cout << "Press <enter> to terminate...";
    std::cin.get(); // Wait for user to end program
    return 0;
}
Parent call
Child call
Child call
Child call
Child call
Press <enter> to terminate...