当我编译时,clang给出以下输出:
插入虚拟方法在构造期间绕过绕过虚拟派遣
注意,如果在混凝土的构造函数中io note消息是什么意思?是警告我,静态调度是进行而不是虚拟调度的,还是对UB的警告?
Concrete::doSomething()
say我们做
Concrete c;
。这就是我认为发生的事情:
c
抽象类的构造函数被称为。
__vptr
指向纯虚拟函数。
称为构造函数。任何非静态成员的初始化。初始化完成了,Concrete
__vptr
的实现。构造函数的主体是运行的,它将称为“被覆盖”。
它是clang-tidy,发出消息LLVM版本17.0.6
从构造函数或破坏者中调用虚拟函数并没有任何固有的错误,并且这样做是not绕过虚拟调度。说那些过分简化的人。
Concrete
真正的规则仅仅是根据构造函数(和破坏者)中的虚拟函数调用,该函数是根据当前正在运行的类的类别的规则来派遣的。
doSomething()
当还有另一个构造水平时,人们往往会感到困惑:
doSomething()
这里的关键是,在构建struct base {
virtual void f() { }
void g() { f(); }
base() {
f(); // always calls base::f
g(); // always calls base::f
}
};
struct intermediate : base {
void f();
intermediate() {
f(); // always calls intermediate::f
g(); // always calls intermediate::f via virtual dispatch
}
};
intermediate i;
// base::base calls to f() and g() both call base::f
// intermediate::intermediate calls to f() and g() both call intermediate::f
i.g(); // calls intermediate::f
的构造函数中没有intermediate
。
intermediate
“绕过”虚拟调度。虚拟函数调用转到针对其构造函数正在运行的类定义的版本。将其描述为“绕过”虚拟调度的人们开始懒惰。声称从构造函数和破坏者中调用虚拟功能的人本质上是危险的人。是的,您必须了解发生了什么。不,这里没有恶魔潜伏。