一、类的封装
- 封装的含义:
- 所有属性都是私有的,外部不能直接访问
- 提供与属性相关的成员函数,间接访问属性
模板代码:
#include <iostream>
using namespace std;
class Clock {
private:
int hour, minute, second;
public:
Clock(); // 声明无参构造函数,用缺省值初始化对象
Clock(int newH, int newM, int newS); // 声明有参构造函数,用传入的参数初始化对象
// 内联函数,设置属性的值
void setHour(int hour) {
this->hour = hour; // 将外部传入的值赋给属性
}
void setMinute(int minute) {
this->minute = minute;
}
void setSecond(int second) {
this->second = second;
}
// 获得属性的值
int getHour() {
return hour;
}
int getMinute() {
return minute;
}
int getSecond() {
return second;
}
void display() {
cout << hour << ":" << minute << ":" << second << endl;
}
};
// 定义无参构造函数,给hour、minute、second赋初值为1
Clock::Clock(): hour(1), minute(1), second(1) {
}
/* 推荐写法:
Clock::Clock() {
this->hour = 1;
this->minute = 1;
this->second = 1;
}
*/
// 定义有参构造函数,给hour、minute、second赋初值为传入的参数值
Clock::Clock(int newH, int newM, int newS): hour(newH), minute(newM), second(newS) {
}
/* 推荐写法:
Clock::Clock(int newH, int newM, int newS) {
this->hour = newH; // 将传入的hour值赋给hour属性
this->minute = newM;
this->second = newS;
}
*/
int main() {
Clock myClock1; // 定义对象,此时自动调用无参构造函数
cout << "利用无参构造函数创建的时间对象为:";
myClock1.display();
Clock myClock2(8, 3, 30); // 定义对象,此时自动调用有参构造函数
cout << "利用有参构造函数创建的时间对象为:";
myClock2.display();
myClock2.setHour(21);
cout << "修改过的对象的时间为:";
myClock2.display();
return 0;
}
二、数据域封装
2.1 数据封装的方法
-
在定义私有数据域的类之外,对象不能通过直接引用访问该数据域
// 这两种方式均错误 myClock.hour = 5; hour = myClock.hour;
-
为了能够访问私有数据域,可以编写一个成员函数返回数据值(如getHour,getMinute),为了能够修改它,可以编写一个成员函数(如setHour,setMinute)进行设置
myClock.setHour(5); hour = myClock.getHour();
2.2 数据封装的优点
2.2.1 防止对封装数据的越权访问
- 如果要隐藏studentID域,实现数据域的保护的方法有:
- 用private声明这个数据
- 不要定义getStudentID函数
class Student {
private:
char studentID[20];
char studentName[20];
......
}
2.2.2 限制私有特性改变时产生的连锁反应
- 属性是私有的,不对外公开,必须要通过getAge函数去读取私有属性(age)的内容
- 一个信息被隐藏的越好,未来可被修改的权利就更大
// 修改前的代码
class Student {
// 定义了age属性
private:
int age;
public:
int getAge(){
return age;
}
...
}
// 修改后的代码
// 把age属性替换成出生年、月、日
class Student {
private:
int birthYear;
int birthMonth;
int birthDate;
public:
int getAge(){
age = 系统时间 - 出生年、月、日
return age;
}
...
}
// 调用代码
// 修改前后调用代码不需要改变
Student s;
int currentAge = s.getAge();
2.2.3 保持数据的完整性
/*
birthdate是私有属性
外界可以修改birthdate,但是数据的格式必须要符合要求,比如mm/dd/yyyy这种,因此可定义一个共有的检查函数updateBirthdate()
先对传过来的新修改的birthdate值进行格式检查,只有当格式符合要求的时候才可以调用私有成员函数setBirthdate()对birthdate进行修改
*/
class Student {
private:
char birthdate[12];
void setBirthdate(char d[]) {
strcpy(birthdate, d);
}
public:
bool updateBirthdate(char d[]) {
if(Data format is not mm/dd/yyyy)
return false;
else if(range of mm or dd is wrong)
return false;
else{
setBirthdate(d);
return true;
}
}
};