虚函数的结构有从简单到复杂的各种情况。什么因素决定了所需的额外内存数量?例如
class A {virtual void F() {} };
class B : public A {virtual void F() {} };
与没有虚函数的类相比,A 和 B 需要多多少内存?另一个带有 2 个虚拟函数的示例,
class A {virtual void F() {} virtual void G() {} };
class B : public A {virtual void F() {} virtual void G() {} };
和示例 3
class A {virtual void F() {}; virtual void G() {} };
class B : public A {virtual void F() {} };
[--------------- 添加更多有趣的问题 ------------------]
每个虚方法都有一个虚方法表吗?如果是这样,我认为对于一个类(不是对象,对吧?我认为VPTR是静态的。)具有多个虚方法需要多个VPTR,每个VPTR对应一个虚方法。对吗?
是否可以为所有虚拟方法只构建一张表,并在一个类中只放置一个 VPTR?
而且我认为由于使用了直接VPTR,所以虚函数的调用速度应该比手动if更快。对吗?
[--------------- 测试 ----------------]
我使用 VS2010 和 intel c++ 编译器进行了测试并展示了我的结果。
struct A
{
static int s_i;
int i;
virtual void F() {i+=1;}
virtual void G() {i+=2;}
};
struct B
: public A
{
int j;
virtual void F() {i+=3;}
virtual void G() {i+=4;}
virtual void H() {i+=5;}
};
struct C
: public B
{
virtual void F() {i+=6;}
virtual void H() {i+=7;}
};
TEST(MemoryForVirtualMethod)
{
CHECK_EQUAL(sizeof(A), 8);
CHECK_EQUAL(sizeof(B), 12);
CHECK_EQUAL(sizeof(C), 12);
}
从结果来看,我的结论是
(1)对于每个具有虚函数的对象,添加一个(隐藏指针)VPTR。
(2)为每个类,为该类的所有虚方法建立一个虚方法表。
(3) 将VPTR放在object中是为了实现动态调度,因为引用的类可能不是动态类。
(4) 该实现调用效率高(比手动 if 更快),但牺牲了一些内存。
非常感谢!
最佳答案
因为虚拟函数通常实现为 virtual method table (vtable) ,我猜测每个类
有O(虚函数数量)
,每个对象
有1个额外的指针。不像你想要的那么精确,但应该给出一个粗略的想法。
正如 @AlokSave 提到的,还有许多其他微妙之处,这些微妙之处是编译器特定的,并且可能不够一致,无法估计。
Typically, the compiler creates a separate vtable for each class. When an object is created, a pointer to this vtable, called the virtual table pointer, vpointer or VPTR, is added as a hidden member of this object
来源:Wikipedia
您重写的函数数量(如您的示例中所示)是(我猜测)无关紧要的,除非可以在编译时安全地确定要调用的函数,在这种情况下它可能被视为静态调度函数(第二个示例中的G()
)。这也取决于编译器。
compilers usually avoid using vtables whenever the call can be resolved at compile time.
最后,虚拟函数的速度成本可能比内存更大。
关于c++ - 虚拟函数需要多少字节的额外内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14473778/