Ⅰ 一个差客服毁掉半个运营:说说那些缺乏“人情味”的游戏客服
有求必应的“机器人”,并不惹人喜爱,有时,会遭人反感。
文/菲斯喵
“我们宁可多‘肝’几天代码,也不想再做一分钟的客服。”
某M曾与葡萄君诉过苦。那时,他主导的 游戏 刚刚上线Steam,遭遇了几多差评。“我们总共也没几个人,只能把开发人员调去做客服。可那些天,玩家可能太激动了,我们兼职做客服的程序员都被‘骂抑郁’了。”
但对于长期处在客服岗位上的人来说,扛着负能量,冲到第一线,去解决玩家的问题,去挽救失陷的口碑,已经成为了工作日常。这么一帮对 游戏 发展、用户留存起到重要作用的人,却常常 被玩家当成了“机器人” ——葡萄君还曾见过有玩家惊呼,“这个和我聊天的,居然是 真人 !”
一位客服从业者在知乎上分享的个人经历
客服的这种固有印象,在哪一行当,都是存在的。究其原因:绕不开这项工作本身有机械办事的特点;近几年AI客服的盛行;以及客服在实际工作中,会用比较定式、套路的交流话术去回应海量用户的问题。
没有人情味 的客服,自然会被玩家视为机冲枣器人。尽管他们有求必应,却 并不惹人喜爱 ; 有时,反而会遭人反感 ,无益于 游戏 的运营。葡萄君觉得,这或许是一个还未被多数厂商所重视的问题。因而在本文中,我们将会试着呈现那些让玩家觉得 “你是机器人” 的几种情况。
我们是如何判断客服缺乏人情味?
这次的观察对象,是TapTap社区中的评论区——我们主要想看看, 在不同 游戏 底下,客服们,是如何针对情况不同的负面评价,去和玩家做互动和交流 。根据回应方式和话术,我们会做出自己的判断:这些 游戏 的客服是否有人格化的特征,以及,他们是如何让人体会不到人情味。
我们觉得,即使是在这种线上公共空间里,客服针对玩家负面评价的回应,也有必要让对方享有愉悦的体验。值得一提的散州拆是,文中讨论的“客服”,并不是专门指处在这个岗位的工作人员,他们也许是运营,也许是开发人员,也许还会是公司的CEO,但 都深度参与到与玩家的沟通工作中 。
另外,葡萄君还想强调一点,我们没有试图去主张, “有人味”就该是各家 游戏 公司在客服工作上,必须追求的方向。 我们也不保证,恪守“有人味”的客服工作标准,就能让 游戏 公司获得非常好的回报。毕竟,具体情况需要具体分析。
我们没有针对谁,也没想说在座的都是如何。只是在此想提醒各家 游戏 厂商, 客服在言行上的无个性、无脑化,也许会造成比较尴尬的情况。
最近我们看到了一例典型:TapTap上有位用户对某款 游戏 进行了一顿吐槽,结果该 游戏 的官方客服,留下了一句“ 感谢支持 ”。当时就有人质疑客服是机器人,另外还有人觉着回复来得毫不过脑。还有句话,我印象特别深刻: 玩家都已经骑到你脸上了,怎么还跟人家说谢谢。
这并非客服与用户的常态交互场景。但留言区中的每一处客服细节,到底还是能让玩家感受到 游戏 厂商的用心程度。
“装死”的客服,或许比机器人更糟糕
有时候,某些 游戏 厂商面对负面评价的处理方式,是“ 无为 ”。在这种思路之下,落到客服层面的具体工作,便是减少回应,甚至是不做回应。由此,让玩家的消极情绪随时间去了。
但葡萄君认为,玩家可能会不喜欢“缺乏人味”的客服,但一定会把“没有人”的客服,拉黑。 我们不倡导冷处理的回应方式,此为下下策 。当问题出现后,玩家需要的,是官方的释疑和态度——这是诚意的体现,也是人情味的流露。但更重要的,客服需要出面引导舆论,避免舆论被意料之外的节奏带走。
我们发现,TapTap上有一款安装量超过90万的放置手游,近期在客服工作上,没有让玩家感到十分满意。被服务的一端,认为官方没有正面回应自己问题和需求,甚至严格管控论坛,禁止负面言谈。这让玩家觉得,这个 游戏 的客服质量有所下降。
游戏 的官方在后来登了一条帖子,对玩家的吐槽做了回应,并希望大家能理性看待客服的工作。但葡萄君觉得,他们的工作做得或许还不够到位,至少,放着评论区中的消极情绪任意发酵了几天,总归是不好的。
回头看看过去,便有前车之鉴:曾经有些 游戏 ,运营上出了事故,结果客服回应冷淡,官方动作缓慢,导致玩家集体被激怒,最后做出“开发票”或是“举报”等比较极端的行为迹饥。
把话说得极好听,却未必有人情味
葡萄君在生活中,并不喜欢礼貌的、漂亮的场面话—— 这些话用词用字很精挑细选,却总给人一种逢场作戏的意味。 而我们要说的第二种缺乏人情味的客服回应,就存在于这种修饰感极强的话术中。
此前有一个例子,是在 游戏 葡萄编辑部有过讨论的。这个例子说的是一款知名IP改编的SLG。 游戏 上线时,它的玩法内容不合粉丝的预期,因此 游戏 在这方面,损失了一些口碑。但官方客服的积极性,是让人看得见的,几乎每一条负面评价下,都有客服人员的身影。 但回应的话术、语言、句式,在我们看来,有欠人情味。
其中有些话,在选词用句方面太过刻意了。以上图为例,从“感谢领主反馈”到“我们的希望”再到“ 一一 记录”和“争取加油”—— 我没法说出这番回应哪里有不妥 ,它的字斟句酌很是漂亮,但僵直的回答逻辑和各种修饰性的描述用上去之后,会让人觉得它 流于场面 。
往重了说,便是 “有点假” 。
这番答复形式,在成为不少 游戏 客服的惯用套路后, 玩家更是对其产生了抵抗力 。还是同样的一款 游戏 ,客服对一位打低星评价的玩家进行了百般恭维,称呼其为“领主大人”。但这位玩家,在其他 游戏 中当够了领主大人之后,这回没有产生很舒适的体验。
这里举出另外一个例子,同样是满篇的漂亮话,看起来没什么问题。但深究起来,却让我觉得它是出于模板的套话。这个例子说的是上架TapTap的某款二次元 游戏 ,有位玩家就 游戏 太“肝”这个问题给出了不高的评价,而后官方客服做出了一个篇幅不小的回应,行文中用足了有网感的词句和符号,而且内容似乎也切中了玩家的问题。
但底下有位玩家,绕开了客服花里胡哨的表述, 直指对方“不说人话” 。
葡萄君认为,自然的、真诚的回应,是 不需要使用太多包装性的东西 。有些客服自然生发的回应,看起来也许和玩家有冲撞,但我会觉得,这种在生活里稀松日常的对话情境,放到虚拟网络中,也依旧会让人感到鲜活。
这番回应,用的则是比较朴实的文字
频繁回应,并不等于说是有人情味
有些客服工作者,态度很认真。例如在TapTap中,这样的客服人员,会逐条扫过差评,回应每一个人的问题。看上去,客服的存在感很高,与玩家的互动工作做得十分到位—— 如果是仅看回应的数量,而不看回应的质量的话。
实际上,葡萄君以为的,那些没有人情味的客服,他们在高频率的互动中,往往只是甩下一句简单、闭环的留言,而 没有给人充分的对话空间 。这种情况之下,难免就有玩家会质疑:这家客服是不是外包的啊?懂不懂 游戏 呢?是不是只会 CRTL C + CRTL V地完成着自己的日常工作呀? 。
某 游戏 客服,在回应玩家问题时,回复风格比较短平快
葡萄君 没有否定这类客服工作风格的意思 。只是想说,在认真和勤勉的基础上,他们或许有做得更好的空间,而这个上升空间,应该就是更深入的了解玩家的需求,与玩家 进行有来有回的沟通 。这番互动尽管会加大客服的工作量,但着实会让人觉得,我是在跟一个鲜活的人进行对话。
相比短平快的客服风格,这类回复会更具交流感
十天前,某手游公司的CEO,在深夜里仍在和TapTap的一个用户进行互动。玩家对该公司旗下的卡牌 游戏 无感,故抛下一星差评。这位CEO见之,没有放弃让对方留下,主动和对方沟通。一来一回的互动中,双方从 游戏 聊到了家庭,聊到了工作。对方可能还是要流失了,但最初有些粗暴的态度为之一转,并对这位CEO夸赞道 “你们官方说话真的强,服务真到位。 ”
你能发现,这位CEO在互动中没说什么漂亮话,只是在夜深人静的时候,试着让对方理解自家 游戏 的乐趣。但就是一些简单的、接地气的文字, 让对方从中感受到了态度和真诚 。
这位CEO把自己的心得了 朋友圈 。他说: “每一条差评,我都会跟他唠嗑唠到天荒地老,能救一条是一条,这是我们的心得,无关岗位职责。”
让开发人员来充当客服,也许更显真诚
有时候,客服之所以显得不真诚,没有人情味,就在于回应让人觉得没有交流的欲望。而其中的原因,或许是出于客服所能掌握的信息不充分,而无法与玩家进行深度沟通。
比如说,同样是面对玩家的负面评价,注重效率的客服回应,通常只是说 “感谢支持,会考虑建议” ;而比较有人情味的客服,会把玩家提出的问题展开,掏出官方自己的思考,说明其中不到位之处,并给出日后的调整方向。
且不论字数多寡,这样的回复是有信息量的。 而言之有物的内容,对比场面话来说,显然是更具人情味。
但有一个矛盾点,在于 不是所有客服都那么了解 游戏 。如果他们只是来收集玩家的反馈,那么便很难代入自己的 情感 。出于这类情况,客服便无法很好的起到桥梁的作用,因为他们未能掌握问题的核心,又不清楚开发人员的真正想法,以致于留给玩家的答复,往往显得不痛不痒,说起话来,也像是在跟人踢皮球。
如果情况允许,为何不让开发参与客服工作中,从中解答一些触及核心,或者是专业性比较强的问题呢?前不久,葡萄君曾与一位CEO聊起这番话题,他们公司发行的 游戏 ,多数属于细分领域。他告诉我:“有些时候,玩家很需要开发者出来发声。你在看这些回复时,会发现一个特点: 开发者的回应通常都很真诚、热情和努力。”
一名 游戏 制作人向玩家提供建议
相比一个某某 游戏 客服的头衔来说,某某 游戏 制作人的头衔,或许更具有说服力。当开发人亲自出现出马与玩家进行沟通,玩家的建议,或许也更容易被听取和吸纳。
做 游戏 ,或许就是做服务
“装死”、“说场面话”、“缺乏交流感”、“有量无质”、“没有触及痛点”等,便是葡萄君在本文中,想就客服工作的“人情味”问题,提醒各个 游戏 厂商需要注意的几点情况。而我们之所以想强调这些问题,也是因为愈发觉得, 游戏 产业与服务行业几乎无异,它讲究的就是良性互动。
葡萄君曾撰文讨论过 游戏 行业到底是不是服务业,当时有位读者如此回复
上述那些被人忽视的情况,未必会影响 游戏 的正常运营。但想做长期效应的企业,一定会把自己的品牌,当做一个“人”来经营。而要经营一个人,便是要树立起他的品格和气质,那么对于 游戏 厂商来说,要做这些,产品是一方面,服务则是另一方面。
Ⅱ 史上最厉害的黑客是谁
李纳斯·托沃兹(Linus Torvalds)
当今世界最着名的电脑程序员、黑客。Linux内核的发明人及该计划的合作者。托瓦兹利用个人时间及器材创造出了这套当今全球最流行的操作系统内核之一。使自由软件从产业思想运动演变成为市场商业运动,从此改变了软件产业,乃至IT产业的面貌。
乍得·斯托曼
个人简介:
圈内头衔:无 (毫不隐藏!)
主要成就:老牌黑客。1971年,斯托曼在街上找到一份MIT的人工智能实验室的工作。当时他是哈佛大学的一名本科生。后来,斯托曼创立了自由软件基金,打破了软件是私有财产的概念。
第一次接触计算机:1969年在IBM 纽约科学中心,时值16岁。
自己独特的黑客工具:在上世纪 80年代, 斯托曼不拿MIT的薪水但继续在其中的一个办公室工作。在那里他创造了一个新的操作系统GNU--GNU是"GNU's Not Unix"的缩写。
鲜为人知的事实:曾获得麦克阿瑟基金24万美元天才奖。
五短身材,不修边幅,过肩长发,连鬓胡子,时髦的半袖沙滩上装,一副披头士的打扮。看起来象现代都市里的野人。 如果他将一件"麻布僧袍"穿在身上,又戴上一顶圆形宽边帽子,有如绘画作品中环绕圣像头上的光环。一眨眼的功夫,他又变成圣经中的耶稣基督的样子,散发着先知般的威严和力量。野人与基督,恰恰就是自由软件的精神领袖理乍得·斯托尔曼的双重属性:他既是当今专有(私有)商业软件领域野蛮的颠覆者,又是无数程序员和用户心目中神圣的自由之神。
Ⅲ 程序员的代码洁癖在什么情况下是一种恶习
当你把【代码清洁】当作目的时,就是恶习了。为什么会存在代码洁癖,究其根本,是我们对“维护代码”这种让人抓狂的事情的实际需求,让我们越来越注意到清洁的重要。比如说 1 == a 这个,如果从来没有把 a == 1 写错成过 a = 1 导致你调式很长时间过,恐怕这个人能难把这个纳入到他的洁癖范畴内,即使他对空格的使用要求近乎苛刻。在我的圈子里面,一直有很多搞单片机的的。这些人主业是做电子甚至是机械的,当需要一个控制器的时候,会用单片机写一些非常小的程序来实现控制。我发现在这个圈子里面,就几乎没有代码洁癖的人,别说洁癖了,代码的基本清洁都看不到,即使这个人在做电路板的时候一板一眼。为什么?因为没有需求,代码本身长度都很小,而且都是写过无数遍的基本套路,甚至大段大段的代码都是用辅助工具直接生成的;这些代码对他们来说,多乱都很难写错,并切,最重要的,这些代码几乎都不需要维护,因为功能简单,程序就是可以做到没有BUG,需要升级的时候也很少。混乱的代码,于他们的工作效率,几乎没有什么影响;相反,由于开发环境难以想象的简陋,整理代码会浪费他们大量时间。既然代码洁癖是由需求引起的,那么我们来反思一个问题:我们做的和我们需要的一致么?其实问题问出来的时候,相信大家有答案了,既然用到了“洁癖”,肯定代表“做多了”,《编程之道》这本故事书里面有个有趣的小故事:一个初学者被要求编写一个财务软件。他疯狂地工作了很多天,但他的主管检视他的程序时发现,它写了一个编辑嚣,一个图形程序集,和人工智能的界面,但是看不到任何跟财务有关的东西。主管要求解释时,程序员被激怒了:你太没耐心了,我会在最后写财务的部分。这就是一个典型程序员在干的事情,所有的优秀程序员都要经历这样的阶段,过度设计、过度优化、过度使用技巧等等等等,因为我们就是这样的群体,对这些的追求就是我们学习编程提高自己的动力,所以我们必然会经历这样的事情
Ⅳ C++库和C库的区别
C++标准库非常大。在C++标准中,关于标准库的规格说明占了密密麻麻300多页,这还不包括标准C库,后者只是 "作为参考"包含在C++库中。
当然,并非总是越大越好,但在现在的情况下,确实越大越好,因为大的库会包含大量的功能。标准库中的功能越多,开发自己的应用程序时能借助的功能就越多。C++库并非提供了一切(没有提供并发和图形用户接口的支持),但确实提供了很多。几乎任何事都可以求助于它。
因
为标准库中东西如此之多,你所选择的类名或函数名就很有可能和标准库中的某个名字相同。为了避免这种情况所造成的名字冲突,实际上标准库中的一切都被放在
名字空间std中。但这带来了一个新问题。无数现有的C++代码都依赖于使用了多年的伪标准库中的功能,例如,声明
在<iostream.h>,<complex.h>,<limits.h>等头文件中的功能。现有软件没有针对使
用名字空间而进行设计,如果用std来包装标准库导致现有代码不能用,将是一种可耻行为。
慑
于被激怒的程序员会产生的破坏力,标准委员会决定为包装了std的那部分标准库构件创建新的头文件名。生成新头文件的方法仅仅是将现有C++头文件名中的
.h 去掉,方法本樱此身不重要,正如最后产生的结果不一致也并不重要一样。所以<iostream.h>变成
了<iostream>,<complex.h>变成了<complex>,等等。对于C头文件,采用同样的方法,
但在每个名字前还要添加一个c。所以C的<string.h>变成了<cstring>,<stdio.h>变成
了<cstdio>,等等。最后一点是,旧的C++头文件是官方所反对使用的(即明确列出不再支持),但旧的C头文件则没有(以保持对C的兼
容性)。实际上,编译器制造商不会停止对客户现有软件提供支持,所以可以预计,旧的C++头文件在未来几年内还是会被支持。
所以,实际来说,下面是C++头文件的现状:
· 旧的C++头文件名如<iostream.h>将会继续被支持,尽管它们不在官方标准中。这些头文件的内容不在名字空间std中。
· 新的C++头文件如<iostream>包含的基本功能和对应的旧头文件相同,但头文件的内容在名字空间std中。(在标准化的过程中,库中有些部分的细节被修改了,所以旧头文件和新头文件中的实体不一定完全对应。)
· 标准C头文件如<stdio.h>继续被支持。头文件的内容不在std中。
· 具有C库功能的新C++头文件具有如<cstdio>这样的名字。它们提供的内容和相应的旧C头文件相同,只是内容在std中。
所
有这些初看有点怪,但不难习惯它。最大的挑战是把字符串头文件理清楚:<string.h>是旧的C头文件,对应的是基于char*的字符串
处理函数;<string>是包装了std的C++头文件,对应的是新的string类;<cstring>是对应于旧C头文件
的std版本。如果能掌握这些,其余的也就容易了。
关
于标准库,需要知道的第二点是,库中的一切几乎都是模板。iostream帮助你操作字符流,但什么是字符?是char吗?是wchar_t?是
Unicode字符?一些其它的多字节字符?没有明显正确的答案,所以标准库让脊返迅你去选。所有的流类(stream
class)实际上是类模板,在实例化流类的时候指定字符类型。例如,标准库将cout类型定义为ostream,但ostream实际上是一个
basic_ostream<char>类型定义(typedef
)。
类
似的考虑适用于标准库中其它大部分类。string不是类,它是类模板:类型参数限定了每个string类中的字符类型。complex不是类,它是类模
板:类型参数限定世悉了每个complex类中实数部分和虚数部分的类型。vector不是类,它是类模板。如此不停地进行下去。
在
标准库中无法避开模板,但如果只是习惯于和char类型的流和字符串打交道,通常可以忽略它们。这是因为,对这些组件的char实例,标准库都为它们定义
了typedef,这样就可以在编程时继续使用cin,cout,cerr等对象,以及istream,ostream,string等类型,不必担心
cin的真实类型是basic_istream<char>以及string的真实类型是
basic_string<char>。
标
准库中很多组件的模板化和上面所建议的大不相同。再看看那个概念上似乎很直观的string。当然,可以基于 "它所包含的字符类型"
确定它的参数,但不同的字符集在细节上有不同,例如,特殊的文件结束字符,拷贝它们的数组的最有效方式,等等。这些特征在标准中被称为traits,它们
在string实例中通过另外一个模板参数指定。此外,string对象要执行动态内存分配和释放,但完成这一任务有很多不同的方法。哪一个最好?选
择:string模板有一个Allocator参数,Allocator类型的对象被用来分配和释放string对象所使用的内存。
这里有一个basic_string模板的完整声明,以及建立在它之上的string类型定义(typedef);可以在<string>头文件中找到它(或与之相当的什么东西):
namespace std {
template<class charT,
class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_string;
typedef basic_string<char> string;
}
注意,basic_string的traits
和Allocator参数有缺省值。这在标准库中是很典型的做法。它为使用者提供了灵活性,但对于这种灵活性所带来的复杂性,那些只想做 "正常"
操作的"典型" 用户却又可以避开。换句话说,如果只想使用象C字符串那样的字符串对象,就可以使用string对象,而不用在意实际上是在用
basic_string<char, char_traits<char>,
allocator<char> >类型的对象。
通常可以这么做,但有时还是得稍稍看看底层。例如,声明一个类而不提供定义具有优点;它还指出,下面是一种声明string类型的错误方法:
class string; // 会通过编译,
先不要考虑名字空间,这里真正的问题在于:string不是一个类,而是一个typedef。如果可以通过下面的方法解决问题就太好了:
typedef basic_string<char> string;
但这又不能通过编译。"所说的basic_string是什么东西?" 编译器会奇怪 ---- 当然,它可能会用不同的语句来问你。所以,为了声明string,首先得声明它所依赖的所有模板。如果可以这么做的话,就会象下面这样:
template<class charT> struct char_traits;
template<class T> class allocator;
template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_string;
typedef basic_string<char> string;
然
而,你不能声明string。至少不应该。这是因为,标准库的实现者声明的stirng(或std名字空间中任何其它东西)可以和标准中所指定的有所不
同,只要最终提供的行为符合标准就行。例如,basic_string的实现可以增加第四个模板参数,但这个参数的缺省值所产生的代码的行为要和标准中所
说的原始的basic_string一致。那到底该怎么办?不要手工声明string(或标准库中其它任何部分)。相反,只用包含一个适当的头文件,
如<string>。
有了头文件和模板的这些知识,现在可以看看标准C++库中有哪些主要组件:
· 标准C库。它还在,还可以用它。虽然有些地方有点小的修修补补,但无论怎么说,还是那个用了多年的C库。
· Iostream。和
"传统"
Iostream的实现相比,它已经被模板化了,继承层次结构也做了修改,增强了抛出异常的能力,可以支持string(通过stringstream
类)和国际化(通过locales)。当然,你期望Iostream库所具有的东西几乎全都继续存在。也就是说,它还是支持流缓冲区,格式化标识符,操作
子和文件,还有cin,cout,cerr和clog对象。这意味着可以把string和文件当做流,还可以对流的行为进行更广泛的控制,包括缓冲和格式
化。
·
String。string对象在大多数应用中被用来消除对char*指针的使用。它们支持你所期望的那些操作(例如,字符串连接,通过
operator[]对单个字符进行常量时间级的访问,等等),它们可以转换成char*,以保持和现有代码的兼容性,它们还自动处理内存管理。一些
string的实现采用了引用计数,这会带来比基于char*的字符串更佳的性能(时间和空间上)。
·
容器。标准库提供了高效的容器实现:vector(就象动态可扩充的数组),list(双链表),queue,
stack,deque,map,set和bitset。但多少可以作为补偿的一点是,
string是容器。这很重要,因为它意味着对容器所做的任何操作对string也适用。
标准库规定了每个类的接口,而且每条接口规范中的一部分是一套性能保证。所以,举例来说,无论vector是如何实现的,仅仅提供对它的元素的访问是不够的,还必须提供 "常量时间" 内的访问。如果不这样,就不是一个有效的vector实现。
很
多C++程序中,动态分配字符串和数组导致大量使用new和delete,new/delete错误 ----
尤其是没有delete掉new出来的内存而导致的泄漏 ----
时常发生。如果使用string和vector对象(二者都执行自身的内存管理)而不使用char*和动态分配的数组的指针,很多new和delete就
可以免于使用,使用它们所带来的问题也会随之消失。
· 算法。标准库就提供了大量简易的方法(即,预定义函数,官方称为算法(algorithm) ---- 实际上是函数模板),其中的大多数适用于库中所有的容器 ---- 以及内建数组(built-in arrays)。
算
法将容器的内容当作序列(sequence),每个算法可以应用于一个容器中所有值所对应的序列,或者一个子序列(subsequence)。标准算法有
for_each(为序列中的每个元素调用某个函数),find(在序列中查找包含某个值的第一个位置,count_if(计算序列中使得某个判定为真的
所有元素的数量),equal(确定两个序列包含的元素的值是否完全相同),search(在一个序列中找出某个子序列的起始位置),(拷贝一个
序列到另一个),unique(在序列中删除重复值),rotate(旋转序列中的值),sort(对序列中的值排序)。注意这里只是抽取了所有算法中的
几个;标准库中还包括其它很多算法。
和容器操作一样,算法也有性能保证。例如,stable_sort算法执行时要求不超过0比较级(N log N) 。(stable_sort提供的性能必须和最高效的通用排序算法在同一个级别。)
· 对国际化的支持。不同的文化以不同的方式行事。和C库一样,C++库提供了很多特性有助于开发出国际化的软件。但虽然从概念上来说和C类似,其实C++的方法还是有所不同。例如,C++为支持国际化广泛使用了模板,还利用了继承和虚函数,这些一定不会让你感到奇怪。
支
持国际化最主要的构件是facets和locales。facets描述的是对一种文化要处理哪些特性,包括排序规则(即,某地区字符集中的字符应该如何
排序),日期和时间应该如何表示,数字和货币值应该如何表示,怎样将信息标识符映射成(自然的)明确的语言信息,等等。locales将多组facets
捆绑在一起。例如,一个关于美国的locale将包括很多facets,描述如何对美国英语字符串排序,如何以适合美国人的方式读写日期和时间,读写货币
和数字值,等等。而对于一个关于法国的locales来说,它描述的是怎么以法国人所习惯的方式完成这些任务。C++允许单个程序中同时存在多个
locales,所以一个应用中的不同部分可能采用的是不同的规范。
·
对数字处理的支持。C++库为复数类(实数和虚数部分的精度可以是float,double或long
double)和专门针对数值编程而设计的特殊数组提供了模板。例如,valarray类型的对象可用来保存可以任意混叠(aliasing)的元素。这
使得编译器可以更充分地进行优化,尤其是对矢量计算机来说。标准库还对两种不同类型的数组片提供了支持,并提供了算法计算内积(inner
proct),部分和(partial
sum),临差(adjacent difference)等。
· 诊断支持。标准库支持三种报错方式:C的断言,错误号,例外。为了有助于为例外类型提供某种结构,标准库定义了下面的例外类(exception class)层次结构:
|---domain_error
|----- logic_error<---- |---invalid_argument
| |---length_error
| |---out_of_range
exception<--|
| |--- range_error
|-----runtime_error<--|---underflow_error
|---overflow_error
logic_error(或它的子类)类型的例外表示的是软件中的逻辑错误。理论上来说,这样的错误可以通过更仔细的程序设计来防止。runtime_error(或它的子类)类型的例外表示的是只有在运行时才能发现的错误。
可以就这样使用它们,可以通过继承它们来创建自己的例外类,或者可以不去管它。没有人强迫你使用它。
上面列出的内容并没有涵盖标准库中的一切。
标准库中容器和算法这部分一般称为标准模板库。STL中实际上还有第三个构件 ---- 迭代子(Iterator)。迭代子是指针似的对象,它让STL算法和容器共同工作。
STL
是标准库中最具创新的部分,这并不是因为它提供了容器和算法(虽然它们非常有用),而是因为它的体系结构。简单来说,它的体系结构具有扩展性:可以对
STL进行添加。当然,标准库中的组件本身是固定的,但如果遵循STL构建的规范,可以写出自己的容器,算法和迭代子,使它们可以和标准STL组件一起工
作,就象标准组件自身之间相互工作一样。还可以利用别人所写的符合STL规范的容器,算法和迭代子,就象别人利用你的一样。使得STL具有创新意义的原因
在于它实际上不是软件,而是一套规范(convention)。标准库中的STL组件只是具体体现了遵循这种规范所能带来的好处。
通过使用标准库中的组件,通常可以避免从头到尾来设计自己的IO流,string,容器,国际化,数值数据结构以及诊断等机制。这就有更多的时间和精力去关注软件开发中真正重要的部分:实现软件的其他功能。