封装是面向对象编程的关键特性之一。它涉及将数据成员和函数捆绑在单个类中。
将相似的数据成员和函数捆绑在类中也有助于数据隐藏。
C++ 封装
总的来说,封装是一个将相似代码包装在一个地方的过程。
在 C++ 中,我们可以将数据成员和操作它们的功能捆绑在单个类中。例如,
class Rectangle {
public:
int length;
int breadth;
int getArea() {
return length * breadth;
}
};
在上面的程序中,函数 getArea()
计算矩形的面积。为了计算面积,它需要长度和宽度。
因此,数据成员(length 和 breadth)和函数 getArea()
被一起放在 Rectangle
类中。

示例 1:C++ 封装
// Program to calculate the area of a rectangle
#include <iostream>
using namespace std;
class Rectangle {
public:
// Variables required for area calculation
int length;
int breadth;
// Constructor to initialize variables
Rectangle(int len, int brth) : length(len), breadth(brth) {}
// Function to calculate area
int getArea() {
return length * breadth;
}
};
int main() {
// Create object of Rectangle class
Rectangle rect(8, 6);
// Call getArea() function
cout << "Area = " << rect.getArea();
return 0;
}
输出
Area = 48
在上面的示例中,我们正在计算矩形的面积。
为了计算面积,我们需要两个变量:length 和 breadth,以及一个函数:getArea()
。因此,我们将这些变量和函数捆绑在一个名为 Rectangle 的类中。
在这里,变量和函数也可以从其他类访问。因此,这不是数据隐藏。
这仅仅是封装。我们只是将相似的代码放在一起。
注意:人们经常将封装视为数据隐藏,但这并不完全正确。
封装是指将相关字段和方法捆绑在一起。这可用于实现数据隐藏。封装本身并不是数据隐藏。
为什么需要封装?
- 在 C++ 中,封装有助于我们将相关数据和函数放在一起,使我们的代码更清晰、更易读。
- 它有助于控制数据成员的修改。
考虑一种情况,我们希望类中的 length 字段是非负的。在这里,我们可以将 length 变量设为私有,并在setAge()
方法中应用逻辑。例如,
class Rectangle { private: int age; public: void setLength(int len) { if (len >= 0) length = len; } };
- getter 和 setter 函数为我们的类成员提供只读或只写访问。例如,
getLength() // provides read-only access setLength() // provides write-only access
- 它有助于解耦系统的组件。例如,我们可以将代码封装到多个模块中。
这些解耦的组件(模块)可以独立且并行地进行开发、测试和调试。并且任何一个组件的更改都不会影响其他组件。 - 我们也可以使用封装来实现数据隐藏。在示例 1 中,如果我们把 length 和 breadth 变量改为
private
或protected
,那么对这些字段的访问就会受到限制。
而且,它们对外部类是隐藏的。这称为数据隐藏。
数据隐藏
数据隐藏是一种通过隐藏实现细节来限制对数据成员访问的方法。封装也为数据隐藏提供了一种方式。
我们可以使用 访问修饰符 来在 C++ 中实现数据隐藏。例如,
示例 2:使用 private 说明符的 C++ 数据隐藏
#include <iostream>
using namespace std;
class Rectangle {
private:
// Variables required for area calculation
int length;
int breadth;
public:
// Setter function for length
void setLength(int len) {
length = len;
}
// Setter function for breadth
void setBreadth(int brth) {
breadth = brth;
}
// Getter function for length
int getLength() {
return length;
}
// Getter function for breadth
int getBreadth() {
return breadth;
}
// Function to calculate area
int getArea() {
return length * breadth;
}
};
int main() {
// Create object of Rectangle class
Rectangle rectangle1;
// Initialize length using Setter function
rectangle1.setLength(8);
// Initialize breadth using Setter function
rectangle1.setBreadth(6);
// Access length using Getter function
cout << "Length = " << rectangle1.getLength() << endl;
// Access breadth using Getter function
cout << "Breadth = " << rectangle1.getBreadth() << endl;
// Call getArea() function
cout << "Area = " << rectangle1.getArea();
return 0;
}
输出
Length = 8 Breadth = 6 Area = 48
在这里,我们将 length 和 breadth 变量设为 private
。
这意味着这些变量不能直接在 Rectangle
类外部访问。
为了访问这些私有变量,我们使用了 public
函数 setLength()
、getLength()
、setBreadth()
和 getBreadth()
。这些被称为 getter 和 setter 函数。
将变量设为私有使我们能够限制来自类外部的未经授权的访问。这就是数据隐藏。
如果我们尝试从 main()
类访问这些变量,将会收到一个错误。
// error: rectangle1.length is inaccessible
rectangle1.length = 8;
// error: rectangle1.breadth is inaccessible
rectangle1.length = 6;