我刚刚开始学习封装,我偶然发现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的行为不同。你为什么相信他们做出了这些改变?
感谢您的时间。
答案 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规则决定,但业务的底线。