信息隐藏
本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 36 课,共 104 课。
信息隐藏不仅仅是使用访问修饰符。它是一种设计原则,要求你不仅隐藏数据,还要隐藏类内部的实现细节。
目标是只公开类的使用者需要了解的内容,同时隐藏其他所有内容。这样,你就可以更改内部实现,而不会影响使用这个类的代码:
class Temperature {
double kelvin; // 内部表示,隐藏的实现细节
public:
void setCelsius(double c) {
kelvin = c + 273.15; // 转换过程对用户隐藏
}
double getCelsius() const {
return kelvin - 273.15;
}
double getFahrenheit() const {
return (kelvin - 273.15) * 9.0/5.0 + 32;
}
};这个类的用户不知道(也不需要知道)温度在内部以开尔文存储。如果你之后决定改用摄氏度存储,只需更改私有实现,公共接口保持不变。
这种将接口与实现分离的做法有几个好处:它降低了类用户的使用复杂度,避免内部数据被意外误用,也让代码更容易维护。隐藏内部细节后,你可以自由地优化或重构,而不会破坏依赖于你的类的现有代码。
挑战
简单我们来创建一个 Distance 类,通过在内部以厘米存储距离来演示信息隐藏,同时提供简洁的接口,让你可以使用不同的单位。使用这个类的人不需要知道(也不必关心)距离在内部是如何存储的,他们只需使用方便的单位即可。
你将创建两个文件来组织代码:
Distance.h:定义一个Distance类,隐藏内部表示形式,同时提供灵活的公共接口。在内部,以 厘米(使用double)存储距离。这是隐藏的实现细节。公共接口应允许用户:- 使用
setMeters(double m)、setCentimeters(double cm)或setKilometers(double km)设置距离 - 使用
getMeters()、getCentimeters()或getKilometers()获取距离:它们都应是 const 方法 - 使用
add(const Distance& other)将两个距离相加,并返回一个新的Distance对象
添加一个默认构造函数,将距离初始化为零。转换逻辑应隐藏在方法中:用户只需调用
setKilometers(5)和getMeters(),无需担心内部存储格式。- 使用
main.cpp:演示用户无需了解内部表示形式,也能使用这个类。从输入中读取两个距离值:第一个以米为单位,第二个以千米为单位。然后:- 创建一个
Distance对象,并使用以米为单位的值设置它 - 打印
"In meters: <value> m" - 打印
"In centimeters: <value> cm" - 打印
"In kilometers: <value> km" - 创建第二个
Distance对象,并使用以千米为单位的值设置它 - 将两个距离相加并保存结果
- 打印
"Combined in meters: <value> m"
- 创建一个
信息隐藏的妙处在于,你以后可以将内部存储单位从厘米改为毫米(或其他单位),而无需更改用户与这个类交互的方式。即使实现发生变化,公共接口也能保持稳定。
使用 <iomanip> 中的 std::fixed 和 std::setprecision(2) 将所有输出值格式化为两位小数。使用 std::stod() 将输入字符串转换为双精度浮点数。
换算参考:1 米 = 100 厘米,1 千米 = 1000 米。
亲手试试
#include <iostream>
#include <string>
#include <iomanip>
#include "Distance.h"
using namespace std;
int main() {
// 读取输入值
string metersInput, kmInput;
cin >> metersInput; // 第一个值,单位为米
cin >> kmInput; // 第二个值,单位为千米
// 使用 std::stod() 将字符串转换为 double 类型
double metersValue = stod(metersInput);
double kmValue = stod(kmInput);
// 设置输出格式
cout << fixed << setprecision(2);
// TODO: 创建第一个 Distance 对象,并用米数值设置它
// TODO: 输出 "In meters: <value> m"
// TODO: 输出 "In centimeters: <value> cm"
// TODO: 输出 "In kilometers: <value> km"
// TODO: 创建第二个 Distance 对象,并用千米数值设置它
// TODO: 使用 add() 方法将两个距离相加
// TODO: 输出 "Combined in meters: <value> m"
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: C++ 在线编译器