__declspec(novtable) and RTTI
来源:互联网 发布:网络黑市网址 编辑:程序博客网 时间:2024/04/29 13:09
Does using __declspec(novtable) on abstract base classes affect RTTI in any way?
Answer
MSVC uses one vptr per object and one vtbl per class
to implement OO mechanism such as RTTI and virtual functions.
So RTTI and virtual functions will work fine if and only if the vptr has been set correctly.
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) );
B should be an abstract class when use __declspec(novtable)
.
There will be no instance of B except in the constructor of D1.
And __declspec(novtable) has no negative affects in most case.
But during the construction of derived class __declspec(novtable)
will make it different from ISO C++ semantic.
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. }};
Note: virtual f() = 0
; makes f to be a pure virtual function
and B to be an abstract class.
The definition
of a pure virtual function could
(not must
) be missing.
C++ allows virtual function call in constructor which we don't recommend.
Update: A mistake in D2 : the vptr in derived constructor.
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};
But vptr is indeterminate during the construction.It's one of the reason that virtual function call in constructor aren't recommend .
If vptr in D2::D2() was B and definition of B::f() was missing, this->f();
will crash when dereference pointer-to-function in the vtbl.
If vptr in D2::D2() was B and B use novtable, this->f();
will crash when dereference an uninitialized vptr.
In fact , vptr in D2::D2() is D2 in MSVC(msvc8).The compiler set vptr to D2 before execute other code in D2::D2().
So this->f();
calls D2::f() and the three assertions will be violated.
- __declspec(novtable) and RTTI
- __declspec(novtable) 的用法
- __declspec(novtable) 的用法
- VC:__declspec(novtable)
- __declspec(novtable) 的用法
- AFX_NOVTABLE与__declspec(novtable)
- AFX_NOVTABLE与__declspec(novtable)
- __declspec(novtable) 的用法
- AFX_NOVTABLE与__declspec(novtable)
- __declspec(novtable) 的用法
- __declspec(novtable)作用
- __declspec(novtable)关键字
- __declspec(novtable) 的用法
- AFX_NOVTABLE与__declspec(novtable)
- __declspec(novtable) 的用法 .
- __declspec(novtable)的作用
- __declspec(novtable)的用法(转)
- __declspec(novtable)有什么作用
- SIP协议解析与实现
- Android开发—数据库应用—访问数据表(SQLite OpenHelper) —查询单条记录、修改
- 修改linux时间
- Shell脚本不能执行问题记录
- 关于C语言中结构体字节对齐问题
- __declspec(novtable) and RTTI
- GIS的新定义
- 用Jedis操作redis缓存
- ptmalloc代码浅析3
- 安装MySQL 5后无法启动(不能Start service)解决方法小结
- JavaScript【表单验证1】
- 2955 Robberies
- 解决Myeclipse导入包出现不了referenced libraries的问题
- C# 中的 ConfigurationManager类引用方法