C++ 数据抽象
数据抽象是指向外界提供仅需的信息,并隐藏其背后的细节,即在程序中代表所需信息而不呈现细节。
数据抽象是一种依赖于接口和实现分离的编程(和设计)技术。
我们以电视为例来说明,你可以打开和关闭电视,切换频道,调节音量,还可以添加外部设备,如扬声器,录像机和DVD播放器,但你不知道其内部细节,也就是说,你不知道它是如何通过空中或有线接收信号,如何转换信号,最终如何在屏幕上显示。
因此,我们可以说电视将其内部实现与外部接口明确分离,并且你可以使用其接口,如电源按钮,频道切换器和音量控制器,而不需要了解其内部。
在C++中,类提供了良好的 数据抽象 。它们向外界提供了足够的公共方法来操作对象功能和数据,即对象的状态,而实际上并不知道类是如何内部实现的。
例如,你的程序可以调用 sort() 函数而不知道该函数实际上使用了哪种算法来对给定的值进行排序。实际上,在库的不同版本中,排序功能的底层实现可能会发生变化,只要接口保持不变,你的函数调用仍然有效。
在C++中,我们使用 类 来定义自己的抽象数据类型(ADT)。你可以使用 ostream 类的 cout 对象将数据流输出到标准输出。
#include <iostream>
using namespace std;
int main() {
cout << "Hello C++" <<endl;
return 0;
}
这里,你不需要理解 cout 如何显示文本在用户的屏幕上。你只需要知道公共接口和底层实现的cout是可以自由改变的。
访问标签强制实现封装
在C++中,我们使用访问标签来定义类的抽象接口。一个类可以包含零个或多个访问标签-
- 使用public标签定义的成员对程序的所有部分都可访问。类型的数据抽象视图由其公开成员定义。
-
使用private标签定义的成员对使用该类的代码不可访问。私有部分隐藏了代码对类型的实现。
对访问标签出现频率没有限制。每个访问标签指定了后续成员定义的访问级别。指定的访问级别在遇到下一个访问标签或看到类体的右括号时保持有效。
数据抽象的好处
数据抽象提供两个重要优势-
- 类的内部保护不被意外的用户级错误所破坏,这可能会破坏对象的状态。
-
类实现可以随着时间的推移而根据需求的变化或错误报告而进行更改,而不需要改变用户级别的代码。
通过仅在类的私有部分定义数据成员,类的作者可以自由地更改数据。如果实现更改,只需要检查类代码以查看更改可能产生的影响。如果数据是公开的,那么任何直接访问旧表示的数据成员的函数都可能被破坏。
数据抽象示例
任何使用公共和私有成员实现类的C++程序都是数据抽象的示例。考虑以下示例-
#include <iostream>
using namespace std;
class Adder {
public:
// constructor
Adder(int i = 0) {
total = i;
}
// interface to outside world
void addNum(int number) {
total += number;
}
// interface to outside world
int getTotal() {
return total;
};
private:
// hidden data from outside world
int total;
};
int main() {
Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
cout << "Total " << a.getTotal() <<endl;
return 0;
}
当上述代码被编译和执行时,产生以下结果−
Total 60
以上的类将数字相加,并返回它们的总和。公共成员- addNum 和 getTotal 是对外界的接口,用户需要知道它们才能使用这个类。私有成员 total 是用户不需要知道的,但是它对于类的正常操作是必需的。
设计策略
抽象将代码分为接口和实现。所以在设计组件时,您必须保持接口与实现的独立性,这样如果您更改底层实现,接口将保持完整。
在这种情况下,使用这些接口的程序将不会受到影响,并且只需要使用最新的实现重新编译。