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

问题描述 投票:4回答:3

我刚刚开始学习封装,我偶然发现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不同的行为。你为什么相信他们做出了这些改变?

谢谢你的时间。

c++ class oop encapsulation
3个回答
1
投票

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

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

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

!2.5。功能指针

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

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

话说回来:

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

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

一旦你离开教室,就要考虑每个编程范例,模型和方法等所规定的每个编程“规则”,作为指导,最佳实践。

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

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

一旦完成这项工作,您就可以坐下来,思考问题,与您的同事和经理讨论,并确定在两周内是否确实有很大的投资回报率来维持封装规则。

您可以确定一件事:如果您在商业环境中工作并且人们通过提供工作软件来谋生,那么决策将不会受到某些教科书中概述的OOP规则的影响,而是由业务的底线决定。


3
投票

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


2
投票

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

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.