`__declspec(novtable)` 没用吗?
Does `__declspec(novtable)` no use?
我们知道,novtable
表示不要为纯抽象class创建虚拟table。但是当我 运行 代码失败时,出了点问题:
#include <iostream>
using namespace std;
struct A{
virtual void fun() = 0;
};
struct __declspec(novtable) B{
virtual void fun() = 0;
};
struct C{
void fun(){}
};
struct _declspec(novtable) D : public A {};
int main(){
cout<<sizeof(int*)<<endl; //4
cout<<sizeof(A)<<endl; //4
cout<<sizeof(B)<<endl; //4
cout<<sizeof(C)<<endl; //1
cout<<sizeof(D)<<endl; //4
return 0;
}
A
和B
大小一样,是不是说novtable
没用了?
ps: 用vs2019编译
The __declspec(novtable)
stops the compiler from generating code to initialize the vfptr
in the constructor(s) and destructor of the class. In many cases, this removes the only references to the vtable
that are associated with the class and, thus, the linker will remove it.
换句话说,vfptr
仍将作为数据成员存在,但其值不会被初始化。例如,如果您设法调用一个纯虚函数,而不是像 "A pure virtual function call" 这样的消息,您将得到一个分段错误。
The size of A
and B
are same, does that means novtable
no use?
__declspec(novtable)
的目的不是减小对象大小,而是去掉一些你不需要的初始化代码和vtable
你也不需要的。
class B
没有 vtable。这并不意味着 B
实例的对象中没有 vtable pointer。需要 vtable 指针以便
例如,如果您创建 BDerived 的实例:
struct BDerived : public B {
void fun() {}
};
BDerived bd;
B* pb = &bd;
pb->fun();
pb
指向一个B
子对象,其中包含一个vtable指针,指向BDerived
的vtable。当你调用 pb->fun()
时,程序会查看 pb
的 vtable 指针,跟随它到 BDerived
的 vtable,然后在那个 vtable 中查找 BDerived
' s 执行 fun
.
换句话说,编译器将代码翻译成这样:
vtable A_vtable = {NULL};
struct A {
vtable *vtable_ptr;
};
// No vtable, but still a vtable pointer
struct B {
vtable *vtable_ptr;
};
void BDerived_fun() {};
vtable BDerived_vtable = {&BDerived_fun};
struct BDerived : public B {
};
BDerived bd; bd.vtable_ptr = &BDerived_vtable;
B* pb = &bd;
(pb->vtable_ptr.fun)(pb);
我们知道,novtable
表示不要为纯抽象class创建虚拟table。但是当我 运行 代码失败时,出了点问题:
#include <iostream>
using namespace std;
struct A{
virtual void fun() = 0;
};
struct __declspec(novtable) B{
virtual void fun() = 0;
};
struct C{
void fun(){}
};
struct _declspec(novtable) D : public A {};
int main(){
cout<<sizeof(int*)<<endl; //4
cout<<sizeof(A)<<endl; //4
cout<<sizeof(B)<<endl; //4
cout<<sizeof(C)<<endl; //1
cout<<sizeof(D)<<endl; //4
return 0;
}
A
和B
大小一样,是不是说novtable
没用了?
ps: 用vs2019编译
The
__declspec(novtable)
stops the compiler from generating code to initialize thevfptr
in the constructor(s) and destructor of the class. In many cases, this removes the only references to thevtable
that are associated with the class and, thus, the linker will remove it.
换句话说,vfptr
仍将作为数据成员存在,但其值不会被初始化。例如,如果您设法调用一个纯虚函数,而不是像 "A pure virtual function call" 这样的消息,您将得到一个分段错误。
The size of
A
andB
are same, does that meansnovtable
no use?
__declspec(novtable)
的目的不是减小对象大小,而是去掉一些你不需要的初始化代码和vtable
你也不需要的。
class B
没有 vtable。这并不意味着 B
实例的对象中没有 vtable pointer。需要 vtable 指针以便
例如,如果您创建 BDerived 的实例:
struct BDerived : public B {
void fun() {}
};
BDerived bd;
B* pb = &bd;
pb->fun();
pb
指向一个B
子对象,其中包含一个vtable指针,指向BDerived
的vtable。当你调用 pb->fun()
时,程序会查看 pb
的 vtable 指针,跟随它到 BDerived
的 vtable,然后在那个 vtable 中查找 BDerived
' s 执行 fun
.
换句话说,编译器将代码翻译成这样:
vtable A_vtable = {NULL};
struct A {
vtable *vtable_ptr;
};
// No vtable, but still a vtable pointer
struct B {
vtable *vtable_ptr;
};
void BDerived_fun() {};
vtable BDerived_vtable = {&BDerived_fun};
struct BDerived : public B {
};
BDerived bd; bd.vtable_ptr = &BDerived_vtable;
B* pb = &bd;
(pb->vtable_ptr.fun)(pb);