免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: asuka2001
打印 上一主题 下一主题

命名难,难于上青天 [复制链接]

论坛徽章:
0
91 [报告]
发表于 2012-02-12 23:56 |只看该作者
本帖最后由 walleeee 于 2012-02-12 23:56 编辑

回复 66# OwnWaterloo


    private有abi问题???没听说过。给个连接我看看。

论坛徽章:
0
92 [报告]
发表于 2012-02-12 23:58 |只看该作者
回复 86# OwnWaterloo


    python有private。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
93 [报告]
发表于 2012-02-13 01:04 |只看该作者
回复 91# walleeee

是相对于opacity type/pimpl/handle-body而言。

使用private,其定义(尤其是布局)对用户代码而言依然是可见的,只是禁止访问而已。编译器会根据这个布局在栈上分配空间
这是实现端与用户端之间隐式二进制协议。
实现端布局改变后,通常就会与已经编译过的用户端不兼容。

而opacity type就几乎完全隐藏了实现细节了,二进制协议只剩下指针的格式,对同一平台来说这通常都是不变的。改动实现细节不需要用户端重新编译。
移植到其他平台时反正实现端与用户端都需要重新编译。
但这种方式不是无代价的,至少会多一层间接性,而且通常是在堆上分配空间

隐藏定义在C与C++中都很容易实现。公开定义在C中就没有强制性手段保证定义不被访问。
但隐藏或公开定义互有优劣,没有哪种一定优于另一种的说法。
在C中公开定义,并通过文档什么的原始手段告之用户不要访问某些成员依然是合理的 —— 就是为了向327说明这个。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
94 [报告]
发表于 2012-02-13 01:17 |只看该作者
本帖最后由 OwnWaterloo 于 2012-02-13 01:19 编辑

回复 92# walleeee

python3.x不了解,但至少python2.x系列我只听说过有 __x 这样的东西。
这其实是可以访问的,大致是 _ClassName__x 这样。
一方面也许只是因为python是动态类型检测而做的妥协。 但这样的机制在实践中也完全够用了。

这恰好说明了要支持信息隐藏语言只需要提供这样一种机制:
库的实现者提出一种建议,避免用户无意识地访问到实现细节, 而非完全禁止用户访问实现细节。
前面也说了, C++,Java,C#里面也根本禁止不了。
以前还见过toplanguage里面有人提出将unix用户权限机制加入到C++中,让C++的权限控制更加灵活(且复杂) —— 完全走火入魔了。

其实根本没必要。只要能避免用户无意间访问就行了,刻意访问肯定有刻意访问的理由,也应该承受相应的代价,成为实现端的一部分,与之一起演化。
只有访问了实现细节的函数(实现端)与不需要访问实现细节的函数(用户端)之分; 什么公有/私有成员函数全都是屁话。

论坛徽章:
0
95 [报告]
发表于 2012-02-13 10:57 |只看该作者
private 只是语法糖而已,不用对它有过多期望,就如同 const、inline 一样,你不用它们也可以写程序,而且一定能达到目的。但是正确使用他们,会让人对代码更放心一点,仅此而已。

至于OW说的布局什么的俺没看懂。我认为只要保证类的成员函数和布局绑定就行了。布局变了,成员函数一定要重新编译的,而access-specifier应该不会影响到布局。

论坛徽章:
0
96 [报告]
发表于 2012-02-13 13:51 |只看该作者
回复 94# OwnWaterloo


    还是‘二十七。。。’说的,c那种adt才是真正的隐藏,而且是‘强隐藏’,而cpp等其他只是'弱隐藏'

论坛徽章:
0
97 [报告]
发表于 2012-02-13 13:56 |只看该作者
回复 93# OwnWaterloo


    你说private破坏abi这一点,我的意思是private本身没有破坏abi,其实是后来修改对象布局以及大小(比如添加/删除变量)带来的访问偏移错误破坏abi。

如果仅仅说隐藏封装,我比较倾向'二十七。。。'的c那种adt方式。这一点大概也是qt为什么到处都是定义指针的考虑之一。

论坛徽章:
0
98 [报告]
发表于 2012-02-13 13:57 |只看该作者
回复 94# OwnWaterloo


    你说的py2那种访问__前缀变量的方式我到时没见过。但是py的这种语义就标准了py也提供了private这种控制方式。

论坛徽章:
0
99 [报告]
发表于 2012-02-13 18:24 |只看该作者
本帖最后由 三月廿七 于 2012-02-13 18:33 编辑
walleeee 发表于 2012-02-13 13:51
回复 94# OwnWaterloo


我估计qt是不开放源码的第三方库,如果 c++ 要实现 "真隐藏",还必须要跟 c 学,全部用指针
这样一来,c 和 c++ 使用方式基本没什么差别了

你说的 ABI 是什么?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
100 [报告]
发表于 2012-02-13 18:40 |只看该作者
回复 95# sonicling

>> private 只是语法糖而已,不用对它有过多期望,就如同 const、inline 一样,你不用它们也可以写程序,而且一定能达到目的。但是正确使用他们,会让人对代码更放心一点,仅此而已。
嗯嗯,private/const它们通常是提供的是一种约束,而不是功能。

>> 而access-specifier应该不会影响到布局。
是有可能的,标准没有禁止。
C结构体中的成员地址必须依次增加。
但C++中只保证同一个access-group?是叫这个名字么?就是一个access-specifier到下一个access-specifier之间的非静态成员是递增的。
不同group之间允许乱排序。 貌似以前有个帖子说gcc有选项可以乱排序。

不过那个回帖不是指的这个问题。



假设:

  1. // libX.h
  2. typedef struct { ... } X;
  3. void f(X* x);

  4. // libX.c
  5. #include "libX.h"
  6. void f(X* x) { ... }

  7. // userX.c
  8. #include "libX.h"
  9. void userX(void) {
  10.       X x; // 这里编译器会按X的定义在栈上分配空间
  11.       f(&x);
  12. ...
复制代码
再假设libX.c的实现需要改变,需要改变X的定义:
1. 如果libX.c与userX.c在同一链接目标(exe/out/dll/so/lib/a)里
libX.h 需要改变。 而且通常Makefile里 userX.c会依赖 libX.h, 所以userX.c也会重新编译。
这还只是引起编译时间增加而已。

2. 如果不在同一链接目标里
很有可能就会忘记重新编译 userX.c, 特别是libX.dll的情况。
如果X需要的成员多了, 基本上已经编译好的 userX 就完蛋了。
即使没有忘记, 如同上面情况1, 又会触发一堆依赖的东西被重新编译。

而如果是:

  1. // libY.h
  2. struct Y;
  3. void g(Y* y);

  4. // libY.c
  5. #include "libY.h"
  6. struct Y { ... }; // 将定义隐藏到该文件内部
  7. void g(Y* y) { ... }

  8. // userY.c
  9. #include "libY.h"
  10. void userY(Y* y) { // 先不考虑y如何得到
  11.       g(y);
  12. ...
复制代码
那么 libY.c 的改变就不会影响userY.c。
无论是否在同一链接目标中, libY.c 重新编译后, 只需要重新链接就可以了。
引起重新编译的依赖就断在这点了, 不会像上面暴露定义那样继续扩散

libY这种方式在C里面通常被称为不透明类型, 在C++里面通常被称为p(pointer/private)impl(implementation)或者handle-body什么的。
我想给327说明这不是无代价的。userY参数那个y是如何得到的?  很多情况下都是libY提供Y* new_Y(...), void delete_Y(Y*) , 并且在堆上分配。
不能因为C没有private, 不能控制 X 中的成员被访问, 就一定要全都采用 libY 的形式。 其实libX 的情况也有很多。



以前,比如327提到的那本java核心编程里,经常有java程序员叫嚣C++的private不是真正的隐藏。
但他们,无论出于什么理由,不会提java的class只能以引用方式使用, 不提其中的效率损失, 不提这其实是一种限制, 不提C++中同样可以这么做。
所以我在提到暴露结构获得效率优势的同时, 也打算顺便提一下其劣势, 避免像那些javaer那样片面。
结果引起这么多误会……
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP