C_and_CPP 版 (精华区)

发信人: seaboy (浪小), 信区: C_and_CPP
标  题: 访问限制
发信站: 哈工大紫丁香 (2003年06月18日09:11:30 星期三), 站内信件


访问限制 

WQ翻译

-------------------------------------------------------------------------------
-

轰。 

巨响自远方传来。感觉上的难受更甚于听觉上的。挖掘队又开始工作了。 

“我希望……”珍妮只开了个头就又没声了。 

“我知道。”我埋头于工作中。过了好一会儿,我加了句:”我也希望能给家里发封信。
但通讯系统必须很快恢复工作才行。” 

“它们能工作,” 珍妮说道。 

轰,又一声巨响。 

“是的,但因为圆屋的系统已被破坏,它被限定为只在紧急事件时使用。我们现在没有被
授权。这是合理的。”我随口答道。 

又一阵的沉默。最后,珍妮低声道:”啊。好吧,他们是这么说的,而现在不是这种情况
?” 

“对。这只是暂时禁止。我也不喜欢这样,但你肯定不认为他们在……”现在是我没声了
。 

轰。 


-------------------------------------------------------------------------------
-

“轰”。 

这就是粘在我的显示器上的便笺上所写的内容。是的,还有跟着一个文件名我知道这个文
件-我稍前加到project中的一个工具类。便笺是用Guru特有的笔法写的,但我搞不懂它是
什么意思。Guru不在,我无法问她。 

就在此时,温迪,我隔间的程序员,进来并坐到她位置上。我探起头,期望于她能明白便
笺的意思。她看起来很憔悴,头枕在手上。 “你看起来有个疯狂的周末,”我冒昧道。 

她无力地点点头。”周五我回到家时,一氧化碳探测器在报警-煤气在泄漏。我们不得不
在一个朋友家渡过周末,直到它修好。我几乎没有合眼-我一直在想,如果没装探测器的
话会发生什么[1] 。” 

“噢,真是千钧一发,”我同情道,并在纸上记下要仔细检查我的探测器。”每个人都好
吧?”温迪点点头。我认为她需要分散一下思维,所以就向她提起这个便笺并问她是什么
意思。 

“等一下,”她答道,”Guru将纸条留在你显示器上?”我点点头。 “My friend,”她
说,”听起来象你当了一回鲍勃。” 

我惊呆了。”你在开玩笑吧!”我脸色发白。Bob was the worst programmer ever鲍勃一
直是最差的程序员,我一有机会就攻击他和他差劲的编程风格。 

温迪摇着她的头,一脸的严肃。 “没有。一直以来他是唯一收到这种神秘纸条的人,如果
你也收到一个,你肯定做了一次坏孩子。让我们看一下源文件。”她转向计算机,登录并
调出有问题的文件。 

我搬过一把椅子。”在我看来,这儿一切都没问题,”我一边说一边从她肩后看过去。 

温迪轻微地动了一下-她比我预料得更专注。”粗看之下没问题,”温迪同意。”也许和
以前的版本比对一下会找到一些线索。”我注视着她使用版本控制系统显示两个版本间的
区别。我注意到-我仍然在试图掌握最基本的checkin/checkout指令,而此时她立刻就调
用了一个版本比对命令。我还在试图归类温迪念出的命令。 

“有了,这而有些说法,但很不关键,”她指着屏幕说。”你更改了类的数据成员。” 

我凑到屏幕前。 “是的,我小小地调整了其实现,我将标识对象位置的3个分开的double
合并为一个double数组。它使得一些成员函数更具效率。但这些成员都是私有的,看到了
吗?” 

class Point
{
private:
    double location[3]; // x, y, z coordinates.
public:
    void setLocation(double x, double y, double z) { 
        location[0]=x; 
        location[1]=y;
        location[2]=z;
   }
    void getLocation(double &x, double& y, double &z) {
        x=location[0]; 
        y=location[1];
        z=location[2];
    }
};

就在这时,我注意到比较器显示文件顶部的一个空行被修改了。”为什么显亮这一行?”
我嚷起来。 

“也许是空格变化,”温迪猜测。”那么,让我们设置为忽略空格。”在一些击键动作后
,于是……这一行仍然处于显亮状态。我将光标定位到这一行,并按下”End”键-骇人听
闻的事情出现了。缩进到最右边的出乎常理地,是这样一条语句: 

      #define private public

温迪和我互相看了一下。. “鲍勃!”我们齐声道。 

鲍勃,就在此时,正向我们走来。Guru不是唯一”说曹操就曹操到”的人。”嗨,新来的,
”他说道,”我正巧路过,就来看一下你是否已经改好了问题。” 

我闭上眼并数十。慢慢地。然后,又数回零。我举起便笺:”你说的是这个问题?”我轻
快地问道。 

“嗨。是的,就是这个。她莫名其妙地将这个留在我的显示器上。当你将x、y和z改到数组
中时,它搞砸了我大部分代码,所以我把它传给了你。改掉它,从现在起再别乱搞了,可
以吧,新来的。” 

“鲍勃,这个#define语句是什么意思?”我指着那行讨厌的代码。 

“哦这个,”鲍勃呵呵笑了。 “很酷的,不是吗?我的代码需要直接访问相关数据。高效
,, y'know你知道的。起先,我只在我自己的代码中使用这个#define语句,但我一直这么
使用,所以很自然地就把它加到你的头文件中了。我要处理非常多的数据运算,所以不能
承受你提供的访问函数的开销。但当你用数组取代了单独的double时,我的代码‘轰’了
。” 

“鲍勃,实际上。”好象事先约好的一样,我们听到了Guru的声音。我们都跳了一下。她
用手指推了一下鼻子上的眼镜。”而且,你对编程原则的曲解”她指责道,”是我留便笺
在你显示器上的原因。你试图搅乱访问控制的行为打破了类的封装。你在代码中将private
改为public的行为违背了One Definition Rule。你必须将你的代码改为使用访问函数。”
 

“我已经说过了,我不能承受访问函数的开销,亲爱的,”鲍勃辩解道。”我必须-” 

“不要说了!” Guru打断了他”访问函数是内联的,不会造成开销。”鲍勃试图反驳,但
Guru阻止了他。”那么,为了避免所有的流言[2],我们用测试来证明访问函数的实际代价
。在此期间,清理掉那些不象样的代码。然后研读并思考1 Meyers 20[3]。” 

鲍勃嘟囔着走向他自己的房间。Guru静静地站着,直到他已经走了,然后领着我回到我自
己的房间。 

“徒弟,”她轻柔地说道,”请写一段测试代码来计算直接访问的开销,和inline的访问
函数以及非inline的访问函数进行对比。要确保非inline的访问函数处理的位于其它的编
译单元中。While you are at it, an inline operator [] would be useful.而inline的
operator []会有帮助。” 

我想了一下。”你是这个意思吗?”我写出: 

class Point
{
public:
    inline double operator[] (int index)  const {
        return location[index];
     }
};

“很好,徒弟。你记住了正确使用const的法则。但现在,这么写它将不只是一个访问函数
,还有个很好的mutator(变异)函数。你能从这个函数得到什么额外的好处?” 

我想了一会儿。”可以在下标上进行越界检查。”我修改了一下: 

class Point
{
public:
    inline double &operator[] (int index) {
        assert(index >=0 && index <= 2);
        return location[index];
     }
};

“嗨,漂亮吧!”这个,我喜欢。”这个越界检查在release版本中没有任何性能开销。”
 

Guru点点头。”并且,”她又说道,”使用一个优化能力很强的编译器时,能生成和直接
访问成员同样高效的代码,而又兼具着封装及其安全性。” 

“所以,”我思索着,”实在没有理由存在公有数据成员,是吧?” 

Guru在回答前停了一下。 “在绝大多数情况下,没有理由。然而,如果一个类仅仅是一个
便利性的数据聚合体,而不是对象模型-也就是说,C风格的struct,只有数据而没有额外
行为-那么将所有数据置为公有是合理的 [4]。” 

“你可以通过访问函数和mutator函数将私有成员暴露出去-但只在它真的有必要时。多余
的Get和Set函数-包括此处的operator []-表明你没有认真考虑封装。当测试表明访问函
数真的存在运行期开销时,你可以通过将它们实现为inline来提高速度。当然,所得的提
高因编译器而异-所以需要测试。” 

“我明白了,老板,”我高兴地回答。她笑了,拢着手静静地走开了。我坐下来写好了测
试代码。其结果,至少就我所使用的编译器而言,非常有趣[5] : 

 Approximate run-time in milliseconds  
Implementation  Optimizations off  Optimizations on  
1: direct access  1061  251  
2: inline accessor function  1673  240  
3: out-of-line accessor function  1662  1432  

-------------------------------------------------------------------------------
-

轰。 

“我不喜欢这样,”珍妮重复道。”他们说圆屋因为一起意外的内部爆炸而被破坏,所以
我们不能去那儿,但那儿的工作还在继续,有着更高许可的人被允许进入并且没有出来过
。他们说远距通讯设施被破坏,并限定只供紧急状态下使用,但我能看到的唯一结果是我
们不能和近木星空间的其他任何人联系。” 

“是吗?” 

“我不喜欢这样。” 

轰。 

我们又有一段时间没说话,最终远处的轰鸣也停止了,但得到的寂静比烦躁的噪音更难受
。left.过了一会儿,珍妮皱起眉头,站起来离开了。 


-------------------------------------------------------------------------------
-

[注释] 
[1] Note from the authors: this situation actually happened to me (Jim) 
recently. I urge all readers to install carbon monoxide and smoke detectors 
and ensure they are well-maintained. I know it's the best investment I've 
ever made! Contact your local fire prevention office for information and 
assistance. 

[2] “Premature optimization is the root of all evil” — Donald Knuth. 
Depending whom you believe, he said it in one or more of: “Structured 
Programming with go to Statements” (Computing Surveys, Vol. 6, No. 4, 
December, 1974, page 268), Literate Programming, or Computer Programming As 
an Art (1974). 

[3] Scott Meyers, Effective C++, 2nd edition, Item 20: “Avoid data members 
in the public interface” (Addison-Wesley, 1997). 

[4] C++ FAQ Lite, Marshall Cline, 
http://www.parashift.com/c++-faq-lite/classes-and-objects.htm#[7.8]. 

[5] The source code and full details of this test are available on the CUJ 
website at hyslop.zip. 
 
--
才知道   
原来
自己需要的是   
100万
份勇气。。。

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.239.80]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.011毫秒