首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >影响std::线程调用哪个虚拟成员函数的睡眠?

影响std::线程调用哪个虚拟成员函数的睡眠?
EN

Stack Overflow用户
提问于 2018-04-20 09:47:14
回答 2查看 331关注 0票数 8

我不确定这是否是c++11中的预期行为。下面是我发现的一个例子。

代码语言:javascript
复制
#include <iostream>
#include <thread>
using namespace std;

class A {
public:
    virtual void a() = 0;
    thread t;
    A() : t(&A::a, this) {}
    virtual ~A() {
        t.join();
    }
};

class B : public A {
public:
    virtual void a() {
        cout << "B::a" << endl;
    }
};

int main() {
    B b;
    this_thread::sleep_for(chrono::seconds(1));
}

编译和运行时

代码语言:javascript
复制
$ g++ -std=c++11 -pthread test.cpp -o test
$ ./test
B::a
$

但当睡眠被移除..。

代码语言:javascript
复制
int main() {
    B b;
    //this_thread::sleep_for(chrono::seconds(1));
}

有些奇怪的事情发生了

代码语言:javascript
复制
$ g++ -std=c++11 -pthread test.cpp -o test
$ ./test
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
$

这会是个窃听器吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-04-20 09:49:37

在构造函数和析构函数中,virtual函数的行为不同。在A的构造函数B中,还没有初始化,这就是为什么还不能调用B的虚拟函数的原因。请参阅virtual

当虚拟函数直接或间接从构造函数或析构函数调用(包括在构造或销毁类的非静态数据成员期间,例如在成员初始化程序列表中),而调用应用的对象是正在构造或销毁的对象时,调用的函数是构造函数或析构函数类中的最终覆盖者,而不是在更派生的类中重写它的函数。换句话说,在构建或破坏过程中,派生更多的类并不存在.

因此,成员函数指针&A::a在调用它时会在另一个线程中得到解析。此调用解析使用虚拟表,因为&A::a是指向虚拟成员函数的指针。构造函数所做的第一件事是设置指向类的虚拟表的虚拟表指针。如果B的构造函数是在调用(this->&A::a)()时输入的,那么它将调用B::a。调用(this->&A::a)()的新线程与执行AB构造函数的当前线程之间存在竞争条件。

票数 10
EN

Stack Overflow用户

发布于 2018-04-21 00:00:16

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49938785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档