C++中结构体和类的关系是什么
小编给大家分享一下C++中结构体和类的关系是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
1、C++结构体和类的关系
为什么讲C++
类的大小要提到结构体呢,因为可能很多和我一样的学子,接触过C语言的结构体对齐,但不明白类的大小怎么计算,这其中都要用到内存对齐的概念,对于内存对齐的概念之前已经说过了,可以参考这篇博客:C++结构体字节对齐和共用体大小 明白结构体的内存大小计算后,就要明白类和结构体的关系:
在C++中,结构体和类的唯一区别就是: 结构体和类具有不同的默认访问控制属性。
类中,对于未指定访问控制属性的成员,其访问控制属性为私有类型(private
)。
结构体中,对于未指定任何访问控制属性的成员,其访问控制属性为公有类型(public
)。
所以结构体的大小和类的大小是一样的,在C++中,结构体也可以实现实现继承和多态(可能很惊讶,可以去看看这篇博文:C++结构体与类的区别详情,还要明确,静态成员变量和成员函数所占用的空间肯定不是结构体或类的空间。还有就是空的类的大小是1字节,以方便类进行实例化。
代码进行验证:
#include <iostream>using namespace std;struct Node {};class Test{};int main () { cout << "sizeof(struct Node) = " << sizeof(Node) << endl; cout << "sizeof(class Test) =" << sizeof(Test) << endl; system("pause"); return 0;}
代码运行结果为:
2、继承类的大小
继承允许我们依据另一个类来定义一个类,会把一个类的成员大小都继承下来,所以继承了的派生类大小一定要考虑基类的大小,首先考虑的最大对齐数,派生类的最大对齐数要考虑基类的最大对齐数。
下面以实际代码进行说明:
#include <iostream>using namespace std;class Base{public: void func() { //成员函数不占用类的空间大小 }private: static int m_val1; // 静态成员不占用类的空间 int m_valInt; char m_valChar; double m_valDouble;};class Son:public Base{public: static int func() { //静态成员函数也不占用内存空间 return 0; }private: int m_sonValint;};int main () { cout << "sizeof(Base) = " << sizeof(Base) << endl; cout << "sizeof(Son) = " << sizeof(Son) << endl; system("pause"); return 0;}
代码运行结果为:
可以明确,静态成员变量和成员函数所占用的空间类的空间,所以Base类的最大对齐数为double类型的大小(8字节),按照顺序存储,
Base类的大小计算应该为:
sizeof(Base)= 4 + 1 + 3(浪费) + 8 = 16字节
Son类继承了Base类,它的最大对齐数也就是8字节,
所以Son类的大小计算应该为:
sizeof(Son) = 4 + 1 + 3(浪费) + 8 + 8 = 24字节
注意类的也要考虑存储顺序,如果把Base类中的m_valChar
放到m_valDouble
后面,
Base类的大小计算就变成了:
sizeof(Base)= 4 + 4(浪费)+ 8 + 1 + 7(浪费)= 24字节
Son类的大小就算就变成了:
sizeof(Son)= 4 + 4(浪费)+ 8 + 1 + 3(浪费) + 4= 24字节
由此可以推算出多继承类的大小计算,菱形继承也是一样,都会继承基类的内存,尤其注意虚继承的情况,虚继承只是避免了菱形继承出现的二义性,但不是不继承,
如以下代码:
#include <iostream>using namespace std;class Base{public: void func() { //成员函数不占用类的空间大小 }public: double m_valDouble;};class Son1:virtual public Base{}; //虚继承class Son2:virtual public Base{}; //虚继承class GrandSon:public Son1,public Son2{};int main () { cout << "sizeof(GrandSon) = " << sizeof(GrandSon) << endl; GrandSon gs; // gs.m_valDouble = 10; //如果不是虚继承就会出现二义性 system("pause"); return 0;}
代码运行结果为:
上述GrandSon
的依旧为16字节,因为它从Son1继承来了一份,又从Son2继承来了一份,所以,虚继承只是避免了访问的二义性,也可见菱形继承会对内存空间造成浪费 。
3、多态类的大小
多态类唯一的区别就是计算类大小要考虑到虚寒表指针的大小,指针的大小和系统相关,32位机器为4字节,64位机器为8字节,指针的大小也要作为最大对齐数的考虑范围。
代码说明如下:
#include <iostream>using namespace std;class Base{public: virtual void func() = 0; //纯虚函数,会生成虚函数表指针public: char m_valChar;};class Son: public Base{public: void func() {};public: int m_SonvalInt;};int main () { cout << "sizeof(Base) = " << sizeof(Base) << endl; cout << "sizeof(Son) = " << sizeof(Son) << endl; system("pause"); return 0;}
代码运行结果为:
Base类的大小为8字节,是因为虚函数表指针占用了4字节,所以Base类的最大对齐数为4字节,虚函数表在构造函数的时候就会生成,所以,虚函数表指针肯定优先存储,
所以Base类大小的计算为:
sizeof(Base) = 4 + 1 + 3(浪费) = 8字节
则Son类的大小计算为:
sizeof(Son)= 4 + 1 + 3(浪费) + 4 = 12字节
以上是“C++中结构体和类的关系是什么”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341