更多课程 选择中心

C/C++培训
达内IT学院

400-111-8989

啥是封装?C++封装小技巧

  • 发布:C++培训
  • 来源:C++资讯
  • 时间:2020-11-27 15:29

将程序中重复出现的代码块提炼成一个函数,也可以理解为一种封装。如果将一个事物相关的数据及对这些数据的处理封装起来,这就是类的概念。毫无疑问,封装可以实现代码的重用、任务的分治、实现(implementaion)和接口(interfavce)的分离以及提高代码的安全性。

1、封装类更易于使用,并降低程序的复杂性。

封装将对象实现的细节隐藏在对象的用户之外。相反,对象的用户通过公共接口访问对象。这样,用户就可以使用对象,而不必了解它是如何实现的。简单说,类由设计者完成实现,而类的使用者只需了解接口即可拿过来使用(实现和接口的分离)。正因为如此,我们才可以在编程语言中使用函数库或类库,而不是每一个程序都要从0开始。

对于完全封装的类,您只需要知道哪些成员函数可以公开使用该类,它们采用什么参数,以及返回什么值。类是如何在内部实现的并不重要。例如,包含一系列名字的类可以使用C风格字符串的动态数组、std::vector、std::map、std::list或许多其他数据结构中的一个来实现。为了使用这个类,您不需要知道(或关心)某个是如何实现的。这大大降低了程序的复杂性,也减少了错误。这比任何其他原因都重要,这是封装的关键优势。

2、封装类有助于保护数据并防止误用

Global variables are dangerous because you don’t have strict control over who has access to the global variable, or how they use it. Classes with public members suffer from the same problem, just on a smaller scale.

全局变量是危险的,因为您无法严格控制谁可以访问全局变量,或如何使用全局变量。有公共成员的类也有同样的问题,只是规模较小。

例如,假设我们正在编写一个字符串类。我们可以这样开始:

class MyString

{

char *m_string; // we'll dynamically allocate our string here

int m_length; // we need to keep track of the string length

};

这两个变量有一个内在的连接:m_length应该始终等于m_string持有的字符串的长度(此连接称为不变量)。如果m_length是公共的,任何人都可以在不更改m_string的情况下更改字符串的长度(反之亦然)。

这会使类处于不一致的状态,这可能会导致各种奇怪的问题。通过将m_length_和m_string设置为私有,用户被迫使用任何可用的公共成员函数来处理类(这些成员函数可以确保m_length_和m_string始终被适当设置)。

我们还可以帮助保护用户避免在使用我们的类时出错。考虑一个具有公共数组成员变量的类:

class IntArray

{

public:

int m_array[10];

};

如果用户可以直接访问数组,则可以使用无效索引下标数组,从而产生意外结果:

int main()

{

IntArray array;

array.m_array[16] = 2; // invalid array index, now we overwrote memory that we don't own

}

但是,如果我们将数组设为私有,则可以强制用户使用一个函数,该函数首先验证索引是否有效:

class IntArray

{

private:

int m_array[10]; // user can not access this directly any more

public:

void setValue(int index, int value)

{

// If the index is invalid, do nothing

if (index < 0 || index >= 10)

return;

m_array[index] = value;

}

};

这样,我们就保护了程序的完整性。顺便说一下,std::array和std::vector的at()函数做了一些非常相似的事情!另外C风格字符串封装为string类,裸指针封装为智能指针都体现了同样的思想。

3、封装类更易于更改

举个简单的例子:

#include <iostream>

class Something

{

public:

int m_value1;

int m_value2;

int m_value3;

};

int main()

{

Something something;

something.m_value1 = 5;

std::cout << something.m_value1 << '\n';

}

虽然这个程序运行良好,但如果我们决定重命名m_value1或更改其类型,会发生什么情况?我们不仅会破坏这个程序,而且很可能大多数使用y类的程序也一样!

封装使我们能够在不破坏所有使用类的程序的情况下更改类的实现方式。

下面是这个类的封装版本,它使用函数访问m_value1:

#include <iostream>

class Something

{

private:

int m_value1;

int m_value2;

int m_value3;

public:

void setValue1(int value) { m_value1 = value; }

int getValue1() { return m_value1; }

};

int main()

{

Something something;

something.setValue1(5);

std::cout << something.getValue1() << '\n';

}

现在,让我们更改类的实现:

#include <iostream>

class Something

{

private:

int m_value[3]; // note: we changed the implementation of this class!

public:

// We have to update any member functions to reflect the new implementation

void setValue1(int value) { m_value[0] = value; }

int getValue1() { return m_value[0]; }

};

int main()

{

// But our program still works just fine!

Something something;

something.setValue1(5);

std::cout << something.getValue1() << '\n';

}

请注意,因为我们没有更改类的公共接口中任何函数的原型,所以使用该类的程序将继续工作,而不会发生任何更改。

4、封装类更易于调试

最后,封装有助于在出现问题时调试程序。通常当程序不能正常工作时,是因为我们的一个成员变量的值不正确。如果每个人都可以直接访问该变量,那么跟踪修改该变量的代码片段可能会很困难(可能是其中的任何一个,您需要对它们进行断点操作才能确定是哪一个)。但是,如果每个人都必须调用同一个公共函数来修改一个值,那么您可以简单地中断该函数并观察每个调用方更改该值,直到您看到它出错的地方。

当你还在担心能否就业时,达内学员提前被企业录取;当你转辗于各大招聘会时,达内学员收到了高薪offer;当你在各大招聘网站投递简历时,达内学员中有人一毕业进入五百强名企。所以选择很重要。找C++培训机构,选达内就对了。

版权声明:转载文章来自公开网络,版权归作者本人所有,推送文章除非无法确认,我们都会注明作者和来源。如果出处有误或侵犯到原作者权益,请与我们联系删除或授权事宜。

预约申请免费试听课

填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:学C++人人都会犯的错误,你犯了吗?
下一篇:现在市场上,C++ 主要用来做什么?

C语言宏定义的几种使用方法

C与C++内存管理避坑指南

C/C++代码规范注释有哪些讲究?

C语言中,全局变量滥用的后果竟如此严重?

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省