打破封装是不是一个好主意?

时间:2014-10-12 21:23:59

标签: c++ class oop encapsulation

我刚刚开始学习封装,我偶然发现std :: string使用的两个函数似乎打破了它的封装。

关于来自http://www.cplusplus.com/reference/string/string/c_str/http://www.cplusplus.com/reference/string/string/data/

的c_str()和data()

“返回的指针指向字符串对象当前使用的内部数组,以存储符合其值的字符”。

对于刚学习OO编程的人来说,破解封装是否是一个好主意? 对于那些更先进的人来说怎么样?

顺便说一句,这似乎与C ++ 98的行为不同。你为什么相信他们做出了这些改变?

感谢您的时间。

3 个答案:

答案 0 :(得分:3)

虽然有时实用性和向后兼容性超越了像Mahmoud那样封装的愿望,但是不要让C ++标准库轻易地破解封装。这个特定点一直存在争议,甚至是许多代码库中的错误来源。 c_str的问题在于,在修改被视为未定义行为的字符串之后,滥用返回的指针值或者长时间保留它会导致内存损坏,但编译器和运行时环境都不能强制执行这种限制,因此在这种情况下,C ++委员会选择了方便而不是安全,并且如果没有充分的理由,就不应该进行权衡。

答案 1 :(得分:2)

关于编程的事情是,你永远不会在你自己的世界里处理你自己的代码。您必须编写代码来汇集各种部件和组件,并且您的代码需要能够执行此操作。

string很棒,毫无疑问。但它们是一种抽象 - 它们提供了一种漂亮,优雅,简单且有用的方式来创建表示文本数据的字节并与之交互。在一天结束的时候,与string一样令人敬畏和精彩,它归结为文本。 ASCII,UTF-8,无论如何,它是文本。如果每个人都可以使用std::string并且你可以在std::string与我交谈,我可以在std::string与你交谈,我们可以幸福快乐地生活在一起。但不幸的是,我们生活在现实世界中,情况并非如此。

迟早,您会发现自己正在使用期望纯文本的C API进行集成。 (什么是纯文本?没有人可以同意。但基本上,指针在某处的内存中指向ASCII / UTF8 / UTF16 / etc编码的字节数组)。他们会要求const char *data,你所拥有的就是你的幻想[{1}}。哦不。

那时候你会意识到你的封装是好的和花花公子,但是为了让你的代码实际做某事有用你需要成为为了您和其他人,能够以通用数据格式访问它。因此,您将开发一个小助手成员函数std::string.c_str(),这将使您可以访问您精致的封装类的核心功能,以便人们可以根据需要从/向其读取/写入,而无需需要被迫使用你工作了很长时间且难以制作的相同封装技术。

特别是在处理诸如整数和字符数组之类的原始数据类型时,您会发现API开发人员经常会避免使用花哨的封装类型,即使他们使用与您相同的语言/工具也是如此。当您发现C ++ API采用或返回.c_int()而不是char *时,请不要感到惊讶。有时他们有充分的理由(祝你好运,试图用一个编译器/标准库编译std::string以实际正确匹配,而不会将你的系统分离到用不同的非ABI兼容编译的代码中库!),有时他们希望将API“简化”到最低限度,以便与其他环境的消费者合作,有时他们根本就没有理由。

答案 2 :(得分:1)

  

我偶然发现std :: string使用的两个函数似乎破坏了它的封装。

您的示例不违反封装规则:

C ++编程语言,第四版,Bjarne Stroustrup:

  

!2.5。功能指针

     

没有字符串隐式转换为char *。那是尝试过的   在许多地方,发现容易出错。相反,标准   library提供显式转换函数c_str()到const   字符*。

同样适用于string::data()。这意味着STL为您提供了一个谨慎的,只读接口,通过该接口可以提取存储在std::string内的数据。这并不违反封装 - 内部数据仍然隐藏在谨慎的界面背后,无法修改。如果存储在字符串对象中的内部数组char 通过使其公开,或者是全局命名空间的一部分,或者通过隐式转换{{{},那么将违反封装。 1}}到string,反之亦然。

说完了:

  

打破封装是不是一个好主意?

如果您的目标是在现实世界中创建有效的应用程序,那么遵循任何编程模型虔诚绝不是一个好主意。

考虑每个节目"规则"一旦你离开教室,每个编程范例,模型和方法等都会列出,作为指南最佳实践

极端示例:您已将复杂的应用程序部署到生产环境中,并且出现了错误。你有一个小时来修复这个错误,或者你失去了工作而你的公司失去了一个客户。 (是的,这种情况确实发生了 - 在那里,做到了......)。您可以进行快速修复,违反封装规则,但会让您的系统在半小时内重新启动并运行。或者,为了遵守封装规则,您可以花两天时间来重构您的应用程序,仔细修改500行代码,将新版本部署到您的测试组,并希望在两周内准备好补丁版本。怎么办?

答案非常明确:至少目前,您将打破封装规则,进行快速而肮脏的修复,让系统重新启动并运行。

一旦得到照顾,您可以坐下来,思考问题,与您的同事和经理讨论,并确定在两周内是否确实有显着的投资回报率来维持封装规则。

您可以确定一件事:如果您在商业环境中工作并且人们通过提供工作软件谋生,那么决定由某些教科书中概述的OOP规则决定,但业务的底线