5类的封装性和信息隐蔽
5.1公用接口与私有实现的分离
通过前面的学习,我们知道C++通过类来实现封装性,把数据和与这些数据有关的操作封装在一个类中。在面向对象编程中,在声明类时,一般都是把所有的数据指定为私有的,使它们与外界隔离。把需要让外界调用的成员函数指定为公用的,外界通过公用的函数来实现对数据的操作。外界与对象唯一的联系渠道就是调用公用的成员函数。这样就使类与外界的联系减少到最低限度。如下是一个测试例子:
可以看到,test类定义了一个成员变量name,然后,提供set_name()、get_name()接口函数来对成员变量name进行操作。
那么,用户不需要直接操作成员变量name,可以通过set_name()、get_name()接口函数来操作。但是,成员变量name是public类型,那么,可以在类外直接访问,例如:
cout"name="t.nameendl;
此时,用户不会被强制通过set_name()、get_name()接口函数来访问成员变量name。那么,有什么方式,可以禁止用户在类外直接访问成员变量name,必须通过接口函数来访问吗?答案是:有,就是我们下面要介绍的知识点“类的封装”特性。
在声明了一个类以后,用户主要是通过调用公用的成员函数来实现类提供的功能,例如对成员变量赋值,显示成员变量的值,对数据进行加工等等。因此,公用成员函数是用户使用类的公用接口(publicinterface),或者说是类的对外接口。
所以,定义一个类,提供公用接口函数。用户可以通过类的公用接口函数,访问和设置类对象的成员变量。同时,把类的成员变量设置为“私有”类型,那么,用户就无法在类外直接访问类的成员变量,只能够通过类提供的公用接口函数来访问。从而保护好类的成员变量,不能够被访问和修改。
信息隐蔽是软件工程中一个非常重要的概念,它的好处在于:如果想修改或扩充类的功能,只需要修改本类中有关的成员变量和与它有关的成员函数,程序中类外的部分可以不必修改。例如,原本有如下的类定义:
classstudent
{
public:
charname[32];
charaddr[32];
longlongnumber;
public:
voidprint()
{
cout"name="nameendl;
cout"addr="addrendl;
cout"number="numberendl;
}
};
想在student类中增加一项成员变量“年龄”,只需这样改:
#includestring.h
#includeiostream
usingnamespacestd;
classstudent
{
public:
charname[32];
charaddr[32];
longlongnumber;
intage;//新增加属性
public:
voidprint()
{
cout"name="nameendl;
cout"addr="addrendl;
cout"number="numberendl;
cout"age="ageendl;
}
};
注意:虽然类中的成员变量改变了,成员函数print的定义改变了,但是,类的对外接口函数print()没有改变,外界仍然通过公用的print()函数访问类中的数据。程序中其他任何部分均无需修改。当然,类的功能改变了,在调用stud对象的print()时,输出该学生的学号、姓名、年龄和性别的值。
可以看出:当接口与实现(对数据的操作)分离时,只要类的接口没有改变,对该类的使用方式没有任何改变。那么,类的定义改变了,但是,对类的使用者来说,类提供的使用接口函数没有改变,那么,对使用者来说就没有太大的影响。提高了代码的移植性能。