当派生类不重写虚函数时,为什么需要 vptr?
class base {
public:
void virtual fn(int i) {
cout << "base" << endl;
}
};
class der : public base{
public:
void fn(char i) {
cout << "der" << endl;
}
};
int main() {
base* p = new der;
char i = 5;
p->fn(i);
cout << sizeof(base);
return 0;
}
尽管函数名称相同,但 base
类中定义的函数 fn 的签名与 der
类中定义的函数 fn()
的签名不同。 因此,在der
类中定义的函数隐藏了base
类函数fn()
。因此 fn 的 der
版本不能通过 p->fn(i)
调用来调用;没关系。
我的观点是,如果不使用 VTABLE,为什么 sizeof
class base
或 der
是 4
指针?这里VTABLE指针有什么要求?
class base {
public:
void virtual fn(int i) {
cout << "base" << endl;
}
};
class der : public base{
public:
void fn(char i) {
cout << "der" << endl;
}
};
int main() {
base* p = new der;
char i = 5;
p->fn(i);
cout << sizeof(base);
return 0;
}
Here signature of function fn defined in base
class is different from signature of function fn()
defined in der
class though function name is same.
Therefore, function defined in der
class hides base
class function fn()
. So class der
version of fn cannot be called by p->fn(i)
call; It is fine.
My point is then why sizeof
class base
or der
is 4
if there is no use of VTABLE pointer? What is requirement of VTABLE pointer here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
请注意,这高度依赖于实现&每个编译器可能会有所不同。
存在
vtable
的要求是基类用于继承和扩展,并且从它派生的类可能会重写该方法。Base 和 Derived 这两个类可能驻留在不同的翻译单元中,编译器在编译 Base 类时不会真正知道该方法是否会被覆盖。因此,如果它找到关键字
virtual
,它就会生成vtable
。Note that this is highly implementation dependent & might vary for each compiler.
The requirement for presence of
vtable
is that the Base class is meant for Inheritance and extension, and a class deriving from it might override the method.The two classes Base and Derived might reside in different Translation Unit and the compiler while compiling the Base class won't really know if the method will be overidden or not. So, if it finds the keyword
virtual
it generates thevtable
.vtable 通常不仅用于虚函数,而且当您执行某些
dynamic_cast
或程序访问类的type_info
时,它还用于标识类类型。如果编译器检测到没有虚函数被重写并且没有使用任何其他功能,它就可以删除 vtable 指针作为优化。
显然,编译器作者认为不值得这么麻烦。可能是因为它不会经常使用,而且您可以通过从基类中删除
virtual
来自己完成此操作。The vtable is usually not only used for virtual functions, but it is also used to identify the class type when you do some
dynamic_cast
or when the program accesses thetype_info
for the class.If the compiler detects that no virtual functions are ever overridden and none of the other features are used, it just could remove the vtable pointer as an optimization.
Obviously the compiler writer hasn't found it worth the trouble of doing this. Probably because it wouldn't be used very often, and because you can do it yourself by removing the
virtual
from the base class.编译器无法优化“基”类中的
vtable
成员变量,因为同一项目或另一个项目中可能存在另一个源文件,其中包含以下内容:析构函数和
fn 可以在其他地方实现:
在另一个地方的某个地方可能有这样的代码:
所以,会有两个问题: 虚拟函数
ived::fn
没有被调用,虚拟析构函数没有被调用,所以BIG_DATA_SIZE
未删除。否则,这里的 sizeof(base) 会有所不同。这就是为什么编译器总是为任何具有虚拟成员函数或虚拟基类的类生成vtable
。关于在派生类中调用析构函数,必须将其视为必须:如果您有任何带有虚函数的类,则该类也应声明虚拟析构函数。
The compiler cannot optimize out
vtable
member variable out of 'base' class, because there could be another source file within the same or another project which would contain the following:The destructor and
fn
could be implemented somewhere else:And somewhere in another place there could be code like this:
So, there would be two problems: virtual function
ived::fn
not called, virtual destructor not called, soBIG_DATA_SIZE
not deleted. Otherwise,sizeof(base)
here would be different. That is why compilers always generatevtable
for any class with a virtual member function or a virtual base class.Regarding calling destructors in derived classes, it must be considered as a must: if you have any class with any virtual function, that class shall also declare a virtual destructor.
继承是一种
is-a
关系。der
是一个base
。base
的大小为4
,der
的大小至少为4
。vftableptr
是base
的成员,它将成为der
的成员。base
有一个虚方法,因此它会有一个指向虚表的指针,无论你是否使用它。Inheritance is a
is-a
relationship.der
is-abase
.base
has size4
,der
will have at least size4
.vftableptr
is a member ofbase
, it will be a member ofder
.base
has a virtual method, so it will have a pointer to the virtual table, regardless of whether you use it or not.