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;如果我们有一个零成员和虚函数的类,那么是如何发生的。请解释一些编程示例。
答案 0 :(得分:5)
每当一个类包含至少一个虚函数时,编译器需要向每个对象添加RunTime Type Information。该实现通常会添加一个指向每个对象的指针,该指针引用由编译器定义并对用户隐藏的结构,指向type_info
对象的指针和用于动态调度函数的vtable
对于没有非静态数据成员且至少有一个虚函数的类,每个对象的大小是每个对象RTTI信息的大小(一个指针),因为它不为零,编译器不会添加额外的空间。引用的内容是sizeof(T) != 0
适用于任何和所有类型T
,具有动态功能的类型通常符合该要求。只有大小为零的类型,编译器才会强制使对象1 char大。
答案 1 :(得分:0)
C ++标准没有定义类的完整布局。这取决于编译器供应商。但是C ++标准确实提供了一些保证。例如,完整对象的大小始终大于零。您在C ++中的Thinking中引用的文字暗示了这条规则的原因。一个简单类的虚函数通常是根据一个额外的隐藏指针成员实现的,该成员识别对象的动态类型,以便可以调用对象动态类型的正确函数。由于这个额外的隐藏成员增加了类的大小,编译器不需要在其中放置任何填充以使类具有非零大小。
但这些主要是实施细节,你不必过于担心。只要你只依赖C ++标准所做的保证,你应该没问题。