深入解析C++编程中类的封装特性

2025-05-29 0 38

共用接口和私有实现的分离

C++通过来实现封装性,把数据和与这些数据有关的操作封装在一个中,或者说,的作用是把数据和算法封装在用户声明的抽象数据型中。

实际上用户往往并不关心的内部是如何实现的,而只需知道调用哪个函数会得到什么结果,能实现什么功能即可。

在声明了一个以后,用户主要是通过调用公用的成员函数来实现提供的功能(例如对数据成员设置值,显示数据成员的值,对数据进行加工等)。因此,公用成员函数是用户使用的公用接口(public interface),或者说是的对外接口。

中被操作的数据是私有的,实现的细节对用户是隐蔽的,这种实现称为私有实现(private implementation)。这种“的公用接口与私有实现的分离”形成了信息隐蔽。

软件工程的一个最基本的原则就是将接口与实现分离,信息隐蔽是软件工程中一个非常重要的概念。它的好处在于:
如果想修改或扩充的功能,只需修改本中有关的数据成员和与它有关的成员函数,程序中外的部分可以不必修改。
如果在编译时发现中的数据读写有错,不必检查整个程序,只需检查本中访问这些数据的少数成员函数。
声明和成员函数的分离

在面向对象的程序开发中,一般做法是将的声明(其中包含成员函数的声明)放在指定的头文件中,用户如果想用该,只要把有关的头文件包含进来即可。

由于在头文件中包含了的声明,因此在程序中就可以用该来定义对象。由于在体中包含了对成员函数的声明,在程序中就可以调用这些对象的公用成员函数。

为了实现上一节所叙述的信息隐蔽,对成员函数的定义一般不放在头文件中,而另外放在一个文件中。

例如,可以分别写两个文件:
student.h头文件

?

1

2

3

4

5

6

7

8

9

10
//这是student.h头文件,在此文件中进行类的声明

class Student //类声明

{

public :

void display( );//公用成员函数原型声明

private :

int num;

char name[20];

char sex;

};

student.cpp

?

1

2

3

4

5

6

7

8

9
// 在此文件中进行函数的定义

#include <iostream>

#include "student.h"//不要漏写此行,否则编译通不过

void Student::display()//在类外定义display类函数

{

cout<<"num:"<<num<<endl;

cout<<"name:"<<name<<endl;

cout<<"sex:"<<sex<<endl;

}

为了组成一个完整的源程序,还应当有包括主函数的源文件(main.cpp):

?

1

2

3

4

5

6

7

8

9
// 主函数模块

#include <iostream>

#include ″student.h″ //将类声明头文件包含进来

int main( )

{

Student stud; //定义对象

stud.display( ); //执行stud对象的display函数

return 0;

}

这是一个包括3个文件的程序,组成两个文件模块:一个是主模块main.cpp,一个是student.cpp。在主模块中又包含头文件student.h。在预编译时会将头文件student.h中的内容取代#include ″student.h″行。

请注意,由于将头文件student.h放在用户当前目录中,因此在文件名两侧用双撇号包起来(″student.h″)而不用尖括号(<student.h>),否则编译时会找不到此文件。

使用C++编译系统对两个源文件main.cpp和student.cpp分别进行编译,得到两个目标程序main.obj和student.obj,然后将它们和其他系统资海连接起来,形成可执行文件main.exe,见图 。

注意,目标文件的后缀在不同的C++编译系统中是不同的,例如在GCC中,后缀是 .o,这里使用 .obj 是对VC 6.0而言。
深入解析C++编程中类的封装特性
在运行程序时调用stud中的display函数,输出各数据成员的值。

有的读者可能会考虑这样一个问题:如果一个声明多次被不同的程序所调用,每次都要对包含成员函数定义的源文件(如上面的student.cpp进行编译,这是否可以改进呢?的确,可以不必每次都对它重复进行编译,而只需编译一次即可。把第一次编译后所形成的目标文件保存起来,以后在需要时把它调出来直接与程序的目标文件相连接即可。 这和使用函数库中的函数是似的。

这也是把成员函数的定义不放在头文件中的一个好处。如果对成员函数的定义也放在声明的头文件中,那么在对使用这些的每一个程序的每一次编译时都必然包括对成员函数定义的编译,即同一个成员函数的定义会多次被重复编译。只有把对成员函数的定义单独放在另一文件中,才能做到单独编译。

在实际工作中,并不是将一个声明做成一个头文件,而是将若干个常用的功能相近的声明集中在一起,形成库。

库有两种:一种是C++编译系统提供的标准库;—种是用户根据自已的需要做成的用户库,提供给自己和自己授权的人使用,这称为自 定义库。在程序开发工作中,库是很有用的,它可以减少用户自己对和成员函数进行定义的工作量。

库包括两个组成部分:声明头文件;已经过编译的成员函数的定义,它是目标文件。

用户只需把库装入到自己的计算机系统中(一般装到C++编译系统所在的子目录下),并在程序中用#include命令行将有关的声明的头文件包含到程序中,就可以使用这些和其中的成员函数,顺利地运行程序。这和在程序中使用C++系统提供的标准函数的方法是一样的,例如用户在调用sin函数时只需将包含声明此函数的头文件包含到程序中,即可调用该库函数,而不必了解sin函数是怎么实现的(函数值是怎样计算出来的)。

当然,前提是系统已装了标准函数库。在用户源文件经过编译后,与系统库(是目标文件)相连接。

在用户程序中包含声明头文件,声明头文件就成为用户使用的公用接口,在头文件的体中还提供了成员函数的函数原型声明,用户只有通过头文件才能使用有关的。用户看得见和接触到的是这个头文件,任何要使用这个的用户只需包含这个头文件即可。包含成员函数定义的文件就是的实现。

请特别注意,声明和函数定义一般是分别放在两个文本中的。由于要求接口与实现分离,为软件开发商向用户提供库创造了很好的条件。

开发商把用户所需的各种的声明按放在不同的头文件中,同时对包含成员函数定义的源文件进行编译,得到成员函数定义的目标代码。软件商向用户提供这些头文件和的实现的目标代码(不提供函数定义的源代码)。用户在使用库中的时,只需将有关头文件包含到自己的程序中,并且在编译后连接成员函数定义的目标代码即可。

由于库的出现,用户可以像使用零件一样方便地使用在实践中积累的通用的或专用的,这就大大减少了程序设计的工作量,有效地提高了工作效率。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 深入解析C++编程中类的封装特性 https://www.kuaiidc.com/106771.html

相关文章

发表评论
暂无评论