首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >打破封装是个好主意吗?

打破封装是个好主意吗?
EN

Stack Overflow用户
提问于 2014-10-12 21:23:59
回答 3查看 692关注 0票数 4

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

关于c_str()和str/http://www.cplusplus.com/reference/string/string/data/中的data()

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

对于刚刚了解OO编程的人来说,打破封装是个好主意吗?对一个更先进的人来说怎么样?

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

谢谢你抽出时间。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-12 22:58:53

我无意中发现了std::string使用的两个函数,它们似乎破坏了它的封装。

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

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

2.5.指向函数的指针 没有将字符串隐式转换为char*。这是在许多地方尝试,并发现容易出错。相反,标准库提供显式转换函数c_str()到const *。

同样适用于string::data()。这意味着STL为您提供了一个离散的、只读的接口,通过它提取存储在std::string中的数据。这不是违反封装-内部数据仍然隐藏在一个离散的接口,不能修改。如果将存储在string对象中的char的内部数组直接公开以供操作,或者使其成为全局命名空间的一部分,或者通过将string隐式转换为char*,则会违反封装,反之亦然。

说了这句话:

打破封装是个好主意吗?

如果您的目标是在现实世界中创建工作应用程序,那么遵循任何编程模型religiously,从来都不是一个好主意。

考虑每一个编程范式、模型和方法等所制定的编程“规则”,作为准则,当您离开教室时,是最佳实践

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

答案是非常清楚的:至少目前,您将打破封装的规则,放入快速和肮脏的修复,并使您的系统重新启动和运行。

一旦解决了这些问题,你就可以坐下来想清楚,和你的同事和经理讨论一下,并决定是否真的有很大的ROI来维持封装的规则。

你可以确定一件事:如果你在一个商业环境中工作,人们通过交付工作软件来谋生,那么的决定将不是由某些教科书中概述的面向对象操作规则( OOP )所决定的,而是由企业的底线来决定的。

票数 2
EN

Stack Overflow用户

发布于 2014-10-12 21:51:28

虽然有时实用程序和向后兼容性压倒了对封装的渴望,就像Mahmoud提到的那样,但不要让C++标准库轻易地被验证以打破封装。这一点一直是有争议的,甚至是许多代码库中bug的来源。c_str的问题是,在修改被认为是未定义的行为的字符串之后,它会导致错误的内存损坏,人们滥用返回的指针值或将其保存太长时间,但是编译器和运行时环境都不能强制执行该限制,因此在这种情况下,C++委员会选择了方便而不是安全,因此不应该在没有充分理由的情况下进行权衡。

票数 3
EN

Stack Overflow用户

发布于 2014-10-12 21:30:54

编程的关键是,你从来没有在你自己的世界里只处理你自己的代码。您必须编写代码来将不同的部分和组件组合在一起,而您的代码需要能够做到这一点。

string是很棒的,毫无疑问。但它们是一种抽象--它们提供了一种很好的、优雅的、简单的和有用的方法来创建并与表示内存中文本数据的字节进行交互。在一天结束的时候,就像一个string一样令人敬畏和辉煌,它归结为文本。ASCII,UTF-8,不管怎么说,都是文字。如果每个人都能用std::string,你可以在std::string和我在std::string和我交谈,我们都可以快乐快乐地生活在一起,那就太棒了。但不幸的是,我们生活在现实世界,事实并非如此。

迟早,您会发现自己与期望纯文本的C API集成。(什么是纯文本?没人能同意。但基本上,指向ASCII/UTF8 8/UTF8 16/etc的指针--内存中某个字节的编码数组)。他们会要求一个const char *data,而你所拥有的只是你的花哨的std::string。哦,不。

这时,您就会意识到您的封装很好,很好,但是为了让您的代码真正做一些事情并使其有用,您需要能够以通用数据格式访问它,这是为了您和其他人。因此,您将开发一个小助手成员函数.c_str().c_int(),它将使您可以访问高级封装类的核心特性,这样人们就可以根据需要对其进行读写,而不必被迫使用您工作了这么长时间且很难完成的封装技术。

特别是在处理诸如整数和字符数组这样的原始数据类型时,您会发现API开发人员往往会避免使用复杂的封装类型,即使他们使用的是与您相同的语言/工具。当您发现C++ API采用或返回char *而不是std::string时,不要感到惊讶。有时候,他们有很好的理由(很幸运地,他们试图让一个用一个编译器/标准库编译的std::string能够真正正确地匹配,而不会将你的系统中的错误与使用不同的、与ABI不兼容的库编译的代码分割!),有时他们希望将他们的API“简化”到最低限度,这样它就可以与其他环境的使用者一起工作,有时他们根本就没有理由。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26330133

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档