C ++中虚拟表的虚拟指针(VPTR)的大小是多少?这也不是一个家庭作业问题......在我阅读C ++书籍时,我想到了一个问题。
答案 0 :(得分:6)
与此主题相关的优秀文章是Member Function Pointers and the Fastest Possible C++ Delegates。本文深入研究了许多不同编译器的成员函数指针的实现。本文讨论了vtable指针的所有细微差别,特别是考虑到多重(和虚拟)继承。
答案 1 :(得分:3)
请注意,为了优雅地处理多重继承,对象中可以有多个VPTR,但通常每个都可能是一个简单的体系结构相关指针。
尝试运行类似这样的内容,看看你的编译器如何解决问题:
#include <iostream>
using namespace std;
struct Base
{
int B;
virtual ~Base() {}
};
struct Base2
{
int B2;
virtual ~Base2() {}
};
struct Derived : public Base, public Base2
{
int D;
};
int main(int argc, char* argv[])
{
cout << "Base:" << sizeof (Base) << endl;
cout << "Base2:" << sizeof (Base2) << endl;
cout << "Derived:" << sizeof (Derived) << endl;
Derived *d = new Derived();
cout << d << endl;
cout << static_cast<Base*>(d) << endl;
cout << &(d->B) << endl;
cout << static_cast<Base2*>(d) << endl;
cout << &(d->B2) << endl;
cout << &(d->D) << endl;
delete d;
return 0;
}
在我的32位编译器上,这为两个基类提供8个字节,为Derived类提供20个字节(并在编译为64位时将这些值加倍):
4 bytes Derived/Base VPTR
4 bytes int B
4 bytes Derived/Base2 VPTR
4 bytes int B2
4 bytes int D
您可以通过查看前8个字节来了解如何将Derived视为Base,以及如何通过查看后8个字节,您可以将其视为Base2。
答案 2 :(得分:2)
这取决于您的实施,但很容易找到。对于这个程序
#include <iostream>
struct virtual_base {
int data;
virtual_base() {}
virtual ~virtual_base() {}
};
struct non_virtual_base {
int data;
non_virtual_base() {}
~non_virtual_base() {}
};
int main() {
std::cout << sizeof( virtual_base ) - sizeof( non_virtual_base ) << '\n';
return 0;
}
我的(VC 2008)将打印4,因此多态性的成本在这种情况下是4字节。
答案 3 :(得分:1)
可能与普通指针的大小相同...通常是32位机器上的4个字节。但这将依赖于编译器,一些编译器可能会以不同的方式做事。
答案 4 :(得分:1)
很可能是任何其他指针的大小。尝试这样的东西来找到你的编译器和机器:
#include <iostream>
struct base {
base() {}
virtual ~base() {}
};
int main( int argc, char **argv ) {
std::cout << sizeof( base ) << std::endl;
}
答案 5 :(得分:1)
虚函数表中的指针通常与系统中常规指针的大小相同。通常,为每种类型计算虚函数表,并且每个对象实例将包含指向其类型表的指针,因此包含虚函数的对象实例将比每个实例使用sizeof(void *)
个字节多。从多个基类型派生的类型必须可转换为任何基类型,因此可以根据需要包含指向基类型的虚函数表的多个指针。当然,所有这些都取决于编译器。