我不确定这是否是c++11中的预期行为。下面是我发现的一个例子。
#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));
}编译和运行时
$ g++ -std=c++11 -pthread test.cpp -o test
$ ./test
B::a
$但当睡眠被移除..。
int main() {
B b;
//this_thread::sleep_for(chrono::seconds(1));
}有些奇怪的事情发生了
$ g++ -std=c++11 -pthread test.cpp -o test
$ ./test
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
$这会是个窃听器吗?
发布于 2018-04-20 09:49:37
在构造函数和析构函数中,virtual函数的行为不同。在A的构造函数B中,还没有初始化,这就是为什么还不能调用B的虚拟函数的原因。请参阅virtual
当虚拟函数直接或间接从构造函数或析构函数调用(包括在构造或销毁类的非静态数据成员期间,例如在成员初始化程序列表中),而调用应用的对象是正在构造或销毁的对象时,调用的函数是构造函数或析构函数类中的最终覆盖者,而不是在更派生的类中重写它的函数。换句话说,在构建或破坏过程中,派生更多的类并不存在.
因此,成员函数指针&A::a在调用它时会在另一个线程中得到解析。此调用解析使用虚拟表,因为&A::a是指向虚拟成员函数的指针。构造函数所做的第一件事是设置指向类的虚拟表的虚拟表指针。如果B的构造函数是在调用(this->&A::a)()时输入的,那么它将调用B::a。调用(this->&A::a)()的新线程与执行A和B构造函数的当前线程之间存在竞争条件。
发布于 2018-04-21 00:00:16
https://stackoverflow.com/questions/49938785
复制相似问题