对话#26:A Midsummer Night’s Madness

类别:VC语言 点击:0 评论:0 推荐:
对话#26:A Midsummer Night’s Madness

“嗯,说吧,你有一小会儿时间?”

我辨认出了从我身后传来的胆小的声音。Kerry,我们部门的新员工,正贴着我的房间站着。他是够聪明的,但……男人,有些搞笑。我曾经这么告诉温迪,但是她只是喃喃自语,大概是有关盆和壶的问题。

“是的,没问题,”我转向他。在Kerry从事的方面我并没有更多的经验,但是被当作老手使人觉得舒服。 我准备着他把什么都丢给我。

“我们伦敦办公室的热线号码是什么?”

我叹了口气。成为指导专家真麻烦。我在便笺上写下号码交给他。

“谢谢,”他一边转身一边说着。“我必须问鲍伯一些事情。”

危险,罗宾森!我的心都提到嗓子眼了。“别!”我脱口而出。

Kerry楞住了。“那是说,别打扰他?”“我的意思是,嗯,”飞快地想着……飞快地想着。“别打扰他。我确信定我们能处理。”

“但鲍伯说我应该离你远点,”Kerry结结巴巴地说道。“他离开前说过,如果我有任何问题,应该打电话给他。他说,'无论你做什么,可千万别……'”

“哦,看一下时间,”我打断道。“伦敦时间现在已经过了下班时间了。鲍伯应该已经离开很久了。”

“但是那里现在才3:30。”

“是的,这是鲍伯的下班时间,我认为。”我大声说道,“鲍伯……当他在伦敦的时候,工作时间变早了。”

“哦。好吧,我想这有道理,”Kerry看起来不太确信,但是他还是坐在我的访客椅上。

“问题是,我有一个接收指标类型的参数的函数,”他边说边在白板上写着:

typedef T* Tptr; 

void f( const Tptr t)

{

*t = T(); // don't want this, but it's allowed

}

“在函数体里,我能修改t,即使我申明它为const 。我也尝试了Tptr const t ,但是它也不起作用。如果我不使用typedef,我知道,我可以写 const T * t,那才是我想要的。”

“啊,”我想了一下。我知道我以前也遇到过这个问题。

 但在哪里?什么时间?“嗯,typedef和宏的文本替换不完全一致。我记不清所有细节了,但我确定,在类型后面加const修饰字时,其行为和你的期望相同。”我稍微地修改了一下代码:

void f( Tptr const t ) // still means T* const

Kerry瞄着新代码。“但是Tptr const t和const Tptr t并不相同。不是吗?”

一个新的声音说:“不!没有不同。”

我为身后Guru的声音所振动。Kerry尖叫着从椅子上跳起来。Guru平静地继续着,合上手中的厚书,对我们的反应视而不见:“告诉我,年轻人, int const i和const int i之间有什么不同?”

Kerry的眼睛睁得很大-非常大,以致于我很好奇于鲍伯对他怎么描述Guru的。Guru则似乎没有注意到他的发抖。

我认为现在最好别参与Guru的行为:“他们是相同的事物。难道不是吗,Kerry?”我提示道。Kerry只是点点头,没说话。

Guru皱了一下眉头。“那么,如果const int和int const是等价的,却期望Tptr const和const Tptr不同,你是这么认为的吧? 嗯?而你不该这么认为的。”

“是的,我正在解释那个部份,”我插了一句嘴。“好吧,Kerry,在这个码中,什么东西是const的?”我写道:

const int i; // or int const i;

“int,”Kerry慢慢说道。这个简单的问题让他恢复了平静。

“好的,”我点头。“现在在这个码中,const的是什么,即使T是个typedef?”我写着:

const T t; // or T const t

“T对象,”Kerry答道,现在比较有自信了。

“好的。现在在这个码中, const的是什么?”我又写:

const Tptr t; // or Tptr const t

“那个……”Kerry吞吞吐吐的。“哦。Tptr?”

“对。但是Tptr表现为一个复合类型,而const只是此类型的一部份。指针本身是const的;这和T* const相同。现在,有多了一点点:在这个码中,什么是const的?”我写着:

const T* t; // or T const* t

“那个……所指向的对象,”他叫了出来。

“对,”我肯定道,并放下书写笔。“这就是const Tptr和 const T*之间的区别。”

Guru把一只手搭在我肩上,又接过话题:“实际上,这是一些先知[1]作以下建议的原因之一:在不改变申明的含义的前提下,将const关键字放在尽可能右边。然后你在心里将typedef作为邪恶的宏展开,”她顿了一下,“以得到正确的含义。”

“是的,但是我总觉得比较拗口,”我抱怨道。“我喜欢申明'const int * iptr',这样当我读它时,我可以念为'常量的int型指针iptr' 。几乎每个人和所有的书,都是这么写它的。另外那种方法感觉比较拗口。”

“拗口?”Guru扬起眉毛。“虽然我们既不推荐也不反对'const在右侧'的风格,但这样做确实有些好处的。它能使得读申明语句比较容易。”

“如何?”Kerry问。

“用编译器使用的方式来读它,你必须这么做。你其实正在的说是'iptr是一个指向const的int的指针', 从右向到左才是'int const * iptr;'的真实含义。”

“但是,那么,我如何申明我的函数以使得T对象真的是const的?”Kerry回到他的最初问题上。

“啊,我的孩子,很简单。”Guru写道:

void f( const T* t )

“但是我真的想要使用typedef,”Kerry反对。

“啊,擦板。如果一定要用typedef,为所需的const T另外定义一个typedef:”

typedef const T* Tcptr;

void f( Tcptr t )

“但仍然要小心,”Guru的话预示着恶兆,“我们已经发现简单地使用typedef来产生一个指针价值非常小。由于我们这里讨论的const缺陷,必须提供两个分开的typedef。这样的typedef增生,而又在意义上区别非常小,只会是造成混乱。也就没什么价值可言。”

Guru又打开她的书,转身离开了。“混乱是编程的黑暗面。太多的typedef,无力的命名-这些都导致……”她的声音伴随着身影消失于某个拐角。

我看了一下Kerry。他盯着我,欲言又止。

“别烦恼,”我安慰他说,“你会习惯她的。她真的是一个极其优秀的程序员。”Kerry眨着眼,张开嘴又闭上,一脸茫然地走开了。我耸耸肩,又回去干活。

[注释]

[1] Notably Dan Saks.

本文地址:http://com.8s8s.com/it/it2299.htm