在C语言中“数据(变量)”和处理数据的操作(函数)是分开声明的,即C语言本身并没有提供“数据和函数”之间直接关联的功能。C++中的class从面向对象出发,将变量和函数集中定义在一起,实现了两者之间的绑定。但从计算机的角度分析,程序同样有数据段和代码段构成,那么C++是如何从面向对象理论到计算机化程序之间的转化的?即C++编译器是如何管理类和对象,以及类和对象之间的关系?类和方法之间的调用关系是怎么实现的?
先看例子:
#include <iostream>
using namespace std;
struct S1 { int a; int b; char c; };
struct S2 { int a; int b; int c; static int d; };
class A { public: int _a; int _b;
private: char _c; };
class B { public: void setA(int a) { _a = a; } int getA() { return _a; }
private: int _a; int _b; int _c; static int _d; };
class sub_A :A { public: void print(int b) { cout << "函数实现" << endl; } private: int sub_a; };
int main() { printf("size S1=%d\n", sizeof(S1)); // 12 printf("size S2=%d\n", sizeof(S2)); // 12 printf("size A=%d\n", sizeof(A)); // 12 printf("size B=%d\n", sizeof(B)); // 12 printf("size sub_A=%d\n", sizeof(sub_A)); // 16 system("pause"); return 0; } |
运行结果:
通过以上案例,我们可以得出:
- C++类中的成员函数和成员变量是分开存储的;
- 成员函数存储在代码区;
- 成员变量
- 普通成员变量存储在类对象中,与struct类型有同样的内存布局和字节对齐方式;
- 静态成员变量存储于全局数据区中;
那问题来了,要是类中包括虚函数会怎么样?
请先看例子
class A { public: void setA(int a) { _a = a; } int getA() { return _a; } virtual void printA() = 0; private: int _a; int _b; int _c; };
class B { public: void setA(int a) { _a = a; } int getA() { return _a; } virtual void printA() = 0; virtual void printB() = 0; private: int _a; int _b; int _c; };
int main() { printf("size A=%d\n", sizeof(A)); // 16 printf("size B=%d\n", sizeof(B)); // 16 system("pause"); return 0; } |
运行结果:
通过调试发现虚函数在类中只保存一个指向虚函数表的(vtable)指针(即_vfptr),vtable用于存放在类中定义的一个或多个虚函数,因此,类只需要维护一个固定大小的指针即可。