06-3 继承中的模型对象模型
思考:从父类继承下来的成员,是否属于子类的对象中呢?
我们可以用sizeof
关键字查看一个对象的大小。
我们可以先创建一个父类:
class A
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
在这个父类A
中,存在着 3 个成员,对应着三个权限:公共权限(public
)、保护权限(protected
)和私有权限(private
),现在,让我们查看一下这个类的对象所占用的内存大小。
#include <iostream>
using namespace std;
class A
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
int main()
{
cout << "int 数据类型所占用的内存空间大小:" << sizeof(int) << endl;
class A a;
cout << "a 类对象所占用的内存空间大小:" << sizeof(a) << endl;
return 0;
}
运行结果:
int 数据类型所占用的内存空间大小:4
a 类对象所占用的内存空间大小:12
可以看到,A
中有三个int
的数据类型,每个int
占用 4 个字节,所以一个A
的对象占用的内存大小是 3 个int
,12 个字节。
这时候我们使用公共继承(public
)来创建一个类:
class B :public A
{
public:
int m_D;
};
提示:任何继承方式都无法访问父类中私有权限(private
)的数据。
然后我们再看一下B
类对象所占用的内存空间大小:
#include <iostream>
using namespace std;
class A
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class B :public A
{
public:
int m_D;
};
int main()
{
cout << "int 数据类型所占用的内存空间大小:" << sizeof(int) << endl;
class A a;
cout << "a 类对象所占用的内存空间大小:" << sizeof(a) << endl;
class B b;
cout << "b 类对象所占用的内存空间大小:" << sizeof(b) << endl;
return 0;
}
运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
int 数据类型所占用的内存空间大小:4
a 类对象所占用的内存空间大小:12
b 类对象所占用的内存空间大小:16
可以看到B
类对象占用了 16 个字节。B
类在父类A
的基础上又创建了一个int
成员,所以B
类中有 4 个int
,所以占用的是 16 个字节。
所以得出结论:子类会继承父类所有的非静态成员属性。
-
复习:
静态成员:静态成员分为:
- 静态成员属性(在成员变量前加上
ststic
)- 所有对象共享一份数据;
- 在编译阶段分配内存(一般的数据存放在栈区)
- 类内声明,类外初始化
- 静态成员函数(在成员函数前加上
ststic
)- 所有对象共享同一个函数
- 静态成员函数只能访问静态成员变量。
- 静态成员属性(在成员变量前加上
父类中私有的成员属性是被编译器隐藏的,所以访问不到。但是会被子类继承。
我们可以在 vs 的“开发人员命令提示符”中查看一下类的数据。
-
查看一下类
A
的:cl /d1 reportSingleClassLayoutA "06-3 继承中的模型对象模型.cpp"
命令行提示:
class A size(12): +--- 0 | m_A 4 | m_B 8 | m_C +---
-
查看一下类
B
的:cl /d1 reportSingleClassLayoutB "06-3 继承中的模型对象模型.cpp"
命令行提示:
class B size(16): +--- 0 | +--- (base class A) 0 | | m_A 4 | | m_B 8 | | m_C | +--- 12 | m_D +---
利用开发人员命令提示符就可以查看对象模型:比如上面就能看到类B
的具体的成员,包括哪一些是继承的,哪一些是自己创建的。
当然,我们也可以再“套娃一下”:
class A
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class B :public A
{
public:
int m_D;
};
class C :public B
{
public:
int m_E;
};
然后查看一下:
cl /d1 reportSingleClassLayoutC "06-3 继承中的模型对象模型.cpp"
命令行提示:
class C size(20):
+---
0 | +--- (base class B)
0 | | +--- (base class A)
0 | | | m_A
4 | | | m_B
8 | | | m_C
| | +---
12 | | m_D
| +---
16 | m_E
+---
- 总结:
- 子类会继承父类所有的非静态成员属性,会占用相应的内存空间。
- 编译器做了隐藏,父类中的私有成员子类无法访问。
- 可以使用“开发人员命令提示符”查看单独类的具体成员,语法如下:
cl /d1 reportSingleClassLayout<类名> <cpp源文件>
。
:-)