gpt4 book ai didi

c++ - 来自子类的虚函数调用一次父函数

转载 作者:太空狗 更新时间:2023-10-29 21:16:06 25 4
gpt4 key购买 nike

这个问题好像和线程有关,运行程序速度很快。我有 2 个类,ThreadParentThreadChild,其中一个继承自另一个。 ThreadParent 创建一个线程并运行函数 func,声明为静态以规避指针问题。然而,我确实希望继承的类(例如 ThreadChild)决定线程究竟做什么,以便 func 调用虚函数 Do

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

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


这是一个小而完整的例子。它创建一个 ThreadChild 对象,每 200 毫秒执行一次 Do。程序在 1 秒后结束(等待输入键)。

#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...

最佳答案

在构造过程中,基类子对象先于派生类构造。在基类体内,动态类型实际上是基类的类型,所以动态函数调度(虚函数调用)会调用基类的相应函数。根据时间的不同,您将看到任一函数被调用。

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

顺便说一句:static 函数是一个转移注意力的问题,您无法避免任何错误。此外,创建线程层次结构通常不是一个好主意。相反,您的类实例代表任务或作业,它们可能会或可能不会在单独的线程中执行。将这些对象紧密耦合到一个线程可能不是一个好主意。此外,将指针传递给基类构造函数的方式似乎很脆弱,因为它创建了一个本来不应该存在的依赖项。

关于c++ - 来自子类的虚函数调用一次父函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36127241/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com