为什么类的大小只包含虚函数时会受到影响?

时间:2011-09-30 07:32:16

标签: c++ function virtual

class classWithNoVirtualFunction
{
    public:
        int   a;
        void x () 
        {
            char c;
            c = 'a';
        }
};

class classWithOneVirtualFunction
{
public:
   int          a;
   virtual void x () {}
};

class classWithTwoVirtualFunctions
{
public:
   int          a;
   virtual void x () {}
   virtual void y () {}
};

int main() 
{
   cout << "\nclassWithNoVirtualFunction's size: "   << sizeof (classWithNoVirtualFunction);    
   cout << "\nclassWithOneVirtualFunction's size: "  << sizeof (classWithOneVirtualFunction);
   cout << "\nclassWithTwoVirtualFunctions's size: " << sizeof (classWithTwoVirtualFunctions);

   cout << "\nvoid*'s size : " << sizeof (void*);
} 

W.R.T上面的代码,Thinking in C ++中说:

  

此示例至少需要一个数据成员。如果没有   数据成员,C ++编译器会强制对象成为一个   非零大小,因为每个对象必须具有不同的地址。如果你   想象一下索引到一个零大小的对象数组,你会   了解。将“虚拟”成员插入到可能的对象中   否则是零大小。

我的问题:现在,我无法理解 what&amp;&amp;如果我们有一个零成员和虚函数的类,那么是如何发生的。请解释一些编程示例。

2 个答案:

答案 0 :(得分:5)

每当一个类包含至少一个虚函数时,编译器需要向每个对象添加RunTime Type Information。该实现通常会添加一个指向每个对象的指针,该指针引用由编译器定义并对用户隐藏的结构,指向type_info对象的指针和用于动态调度函数的vtable

对于没有非静态数据成员且至少有一个虚函数的类,每个对象的大小是每个对象RTTI信息的大小(一个指针),因为它不为零,编译器不会添加额外的空间。引用的内容是sizeof(T) != 0适用于任何和所有类型T,具有动态功能的类型通常符合该要求。只有大小为零的类型,编译器才会强制使对象1 char大。

答案 1 :(得分:0)

C ++标准没有定义类的完整布局。这取决于编译器供应商。但是C ++标准确实提供了一些保证。例如,完整对象的大小始终大于零。您在C ++中的Thinking中引用的文字暗示了这条规则的原因。一个简单类的虚函数通常是根据一个额外的隐藏指针成员实现的,该成员识别对象的动态类型,以便可以调用对象动态类型的正确函数。由于这个额外的隐藏成员增加了类的大小,编译器不需要在其中放置任何填充以使类具有非零大小。

但这些主要是实施细节,你不必过于担心。只要你只依赖C ++标准所做的保证,你应该没问题。