什么是封装,C++类的封装特性(新手必看)
类作为 C++ 与面向对象程序设计相结合的产物,是面向对象程序设计在 C++ 中的具体体现。类的设计从成员构成到类之间的继承关系,再到虚函数,都体现了面向对象程序设计的封装、继承和多态这三大特征。
那么,封装的具体含义到底是什么呢?
虽然老师的具体个体各异,但他们都属于同一类对象—老师。在 C++ 中,我们用类的概念来描述同一类对象,而抽象正是这一过程的第一步。
抽象一般包括属性抽象和行为抽象:
从这个角度看,抽象过程是从具体(各位老师)到一般(变量和函数)的过程。
如果抽象是提取同类对象的共有属性和行为,并用变量和函数来表达,那么封装机制则是将变量和函数捆绑在一起,形成一个完整的类。
在C++中,我们可以使用类(class)来封装分析得到的变量和函数,使其成为类的成员,从而完整地表现这类对象的属性和行为。
例如,我们可以将老师这类对象封装为一个类:
现在有了抽象的 Teacher 类,就可以用它来定义某个对象,进而用这个对象来描述某位具体的老师,这又是一个从抽象到具体的过程。例如:
通过类的封装,我们还可以有效地隐藏对对象的属性和行为。因为访问控制的限制,外界无法直接访问类的隐藏信息。对于类中的一些敏感数据,我们可以将其设置为受保护或私有的成员,就可以防止这些敏感数据被意外修改。
同时,封装好的类通过特定的外部接口(公有的成员函数)向外提供服务。在这个过程中,外界只能看到服务接口的名称和所需的参数,并不知道(也不需要知道)类的内部具体实现的细节。通过这种方式,类实现了对属性内容和行为实现的隐藏,如下图所示。

图 1 抽象与封装
抽象与封装用于将现实世界的对象转变为 C++ 世界中的各个类,即用程序设计语言来描述现实世界。
面向过程程序设计也有抽象这个过程,但它的抽象仅针对现实世界中的过程,而面向对象程序设计的抽象不仅包括对象的属性值(即数据),还包括对象的行为。此外,面向对象程序设计还通过封装将数据和行为有机地结合在一起,形成类,从而更真实地反映现实世界。
抽象与封装完成了从现实世界中的具体对象到C++世界中类的转换,是将现实世界程序化的第一步,也是最重要的一步。
那么,封装的具体含义到底是什么呢?
用类机制实现封装
考虑这样一个现实问题:学校有多位老师,每位老师的名字、年龄等属性各不相同,但这些老师都具有备课和上课等相同的行为。在程序中,我们如何描述这些老师呢?虽然老师的具体个体各异,但他们都属于同一类对象—老师。在 C++ 中,我们用类的概念来描述同一类对象,而抽象正是这一过程的第一步。
抽象一般包括属性抽象和行为抽象:
- 属性抽象关注的是一类对象的共有属性,例如老师都有年龄、姓名等描述其状态的数据。在程序中,我们可以用变量表达这些属性,例如用 m_nAge 变量表示年龄,用 m_strName 变量表示姓名;
- 行为抽象则关注的是一类对象的共有行为,例如老师会备课和上课等。我们可以用函数来表达这些行为,例如用 PrepareLesson() 函数表达老师的备课行为,用 GiveLesson() 函数表达老师的上课行为。
从这个角度看,抽象过程是从具体(各位老师)到一般(变量和函数)的过程。
如果抽象是提取同类对象的共有属性和行为,并用变量和函数来表达,那么封装机制则是将变量和函数捆绑在一起,形成一个完整的类。
在C++中,我们可以使用类(class)来封装分析得到的变量和函数,使其成为类的成员,从而完整地表现这类对象的属性和行为。
例如,我们可以将老师这类对象封装为一个类:
// 用 Teacher 类封装老师的属性和行为 class Teacher { // 构造函数 public: // 根据名字构造老师对象 Teacher(string strName) { m_strName = strName; } // 用成员函数描述老师的行为 public: void PrepareLesson(); // 备课 void GiveLesson(); // 上课 void ReviewHomework(); // 批改作业 // 其他成员函数 // 用成员变量描述老师的属性 protected: string m_strName; // 姓名 int m_nAge; // 年龄 bool m_bMale; // 性别 int m_nDuty; // 职务 private: };通过封装,可以将老师这类对象的共有属性和行为紧密结合在 Teacher 类中,从而形成一个可重用的类。从现实中的老师到 Teacher 类,是一个从具体到抽象的过程。
现在有了抽象的 Teacher 类,就可以用它来定义某个对象,进而用这个对象来描述某位具体的老师,这又是一个从抽象到具体的过程。例如:
// 创建 Teacher 类的对象来描述学校中的某位陈老师 Teacher MrChen("Chen"); // 创建 Teacher 类的对象来描述学校中的某位王老师 Teacher MrWang("Wang");虽然 MrChen 和 MrWang 这两个对象都是 Teacher 类的实例,但由于它们的属性不同,因此可以描述现实世界中两位不同的老师。
通过类的封装,我们还可以有效地隐藏对对象的属性和行为。因为访问控制的限制,外界无法直接访问类的隐藏信息。对于类中的一些敏感数据,我们可以将其设置为受保护或私有的成员,就可以防止这些敏感数据被意外修改。
同时,封装好的类通过特定的外部接口(公有的成员函数)向外提供服务。在这个过程中,外界只能看到服务接口的名称和所需的参数,并不知道(也不需要知道)类的内部具体实现的细节。通过这种方式,类实现了对属性内容和行为实现的隐藏,如下图所示。

图 1 抽象与封装
抽象与封装用于将现实世界的对象转变为 C++ 世界中的各个类,即用程序设计语言来描述现实世界。
面向过程程序设计也有抽象这个过程,但它的抽象仅针对现实世界中的过程,而面向对象程序设计的抽象不仅包括对象的属性值(即数据),还包括对象的行为。此外,面向对象程序设计还通过封装将数据和行为有机地结合在一起,形成类,从而更真实地反映现实世界。
抽象与封装完成了从现实世界中的具体对象到C++世界中类的转换,是将现实世界程序化的第一步,也是最重要的一步。