gpt4 book ai didi

c++ - 在抽象基类上使用 __declspec(novtable) 是否会以任何方式影响 RTTI?

转载 作者:可可西里 更新时间:2023-11-01 15:11:14 25 4
gpt4 key购买 nike

或者,使用 __declspec(novtable) 是否有任何其他已知的负面影响?我似乎找不到任何问题的引用。

最佳答案

MSCV 使用每个对象一个 vptr,每个类一个 vtbl 来实现 OO 机制,例如 RTTI 和虚函数。
因此,当且仅当 vptr 已正确设置时,RTTI 和虚函数才能正常工作。

struct __declspec(novtable) B {
virtual void f() = 0;
};
struct D1 : B {
D1() {
} // after the construction of D1, vptr will be set to vtbl of D1.
};
D1 d1; // after d has been fully constructed, vptr is correct.
B& b = d1; // so virtual functions and RTTI will work.
b.f(); // calls D1::f();
assert( dynamic_cast<D1*>(&b) );
assert( typeid(b) == typeid(D1) );

使用__declspec(novtable)时B应该是一个抽象类。
除了 D1 的构造函数之外,不会有 B 的实例。
而 __declspec(novtable) 在大多数情况下没有负面影响。

但是在派生类的构造过程中,__declspec(novtable)会使其不同于ISO C++语义。

struct D2 : B {


D2() { // when enter the constructor of D2 \
// the vtpr must be set to vptr of B \
// if B didn't use __declspec(novtable).
// virtual functions and RTTI will also work.

this->f(); // should calls B::f();
assert( typeid(*this) == typeid(B) );
assert( !dynamic_cast<D2*>(this) );
assert( dynamic_cast<B*>(this) );

// but __declspec(novtable) will stop the compiler \
// from generating code to initialize the vptr.
// so the code above will crash because of uninitialized vptr.
}
};

注意:虚拟 f() = 0;让 f 成为一个纯虚函数,让 B 成为一个抽象类。
纯虚函数的定义可以(不是必须)缺失。
C++ 允许在我们不推荐的构造函数中调用虚函数。

更新:D2 中的错误:派生构造函数中的 vptr。

struct D3 : B {  // ISO C++ semantic
D3() { // vptr must be set to vtbl of B before enter
} // vptr must be set to vtbl of D2 after leave
};

但是vptr在构造过程中是不确定的,这也是不推荐在构造函数中调用虚函数的原因之一。

如果 D2::D2() 中的 vptr 是 B 并且缺少 B::f() 的定义,this->f(); 将在取消引用函数指针时崩溃vtbl.
如果 D2::D2() 中的 vptr 是 B 并且 B 使用 novtable,this->f(); 将在取消引用未初始化的 vptr 时崩溃。

事实上,D2::D2()中的vptr是MSVC(msvc8)中的D2。编译器在执行D2::D2()中的其他代码之前将vptr设置为D2。
所以 this->f(); 调用 D2::f() 并且三个断言将被违反。

关于c++ - 在抽象基类上使用 __declspec(novtable) 是否会以任何方式影响 RTTI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1801258/

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