Rise的自留地

记录生活中的点滴,分享编程技术和游戏开发经验。

0%

历史地看,中西医的产生与发展过程有着本质的不同,这种差异导致了这两种医学的认识论与方法论的根本性区别。

      中医理论是从人对自身乃至宇宙万物的生命及其能量流动的深刻体验出发的,中医治病的原理就是调整人身的能量动态使之归于平衡的常态,中医的一切理论都是围绕这种能量状态的消长变化展开的,理法方药莫不如此。如果偏离了这种观察思考的角度,处方用药必将变得毫无方向。所以中医学是以理论为第一要义的,经验只是在理论指导下的实践的积累。离开了中医的基本理论,即使用中药治病,也只能是简单的经验医学,不能归入中医纯粹的辨证施治体系了。

      西医是随着解剖学与化学的发展产生并发展起来的,由于起点远离了直接的生命体验,导致了其认识论与方法论的机械主义倾向。一般来说,西医是把人体当作一部机器对待的,西医的治疗方法除了作用于诸大系统的内科化学疗法外,外科的方法更像是木匠或裁缝工作。这样就忽略了作为一个生命体的个人的生命力的能量存在状态,及其作用于人的直接或即发性病理状态。由于其认识论与方法论的局限,导致了西医治疗学体系的重大缺陷——无法正确诊断能量状态的非常态客观存在。常见的现实如:病人能够很明显地感觉得到自身的某种不适症状,但经过西医病理检查,却被告知没有病,于是,对于病人来说很现实的客观症状就被歪曲成了一种主观错觉。还有诸如手术后病人已经死亡,却得出了手术非常成功的荒谬结论,等等。

      这些现象从本质上来说都是由于其认识论与方法论的先天缺陷造成的,中医的认识论与方法论的客观实在性与可验证性,证实了中医理论针对疾病治疗的正确性的同时,也从客观上弥补了西医方法论上的这种先天不足。可惜绝大多数自以为很了解西医很相信科学的明白人并不能清醒地认识到这一点,他们熟视无睹或有意回避其局限性,科学在他们的头脑中已经图腾为一种拜物教似的迷信。
  
中医治病是以十全(100%)为最终目的的,但由于客观因素的局限,能够达到十全的上工寥寥无几。西医是以十全六七(60%-70%)为目的的,只要整体上达到这样的有效率就算成功。

中医自古就是以个体行医的,治疗对象也是个体,不会等到凑全人数才开始治疗。西医是以群体行医,治疗是分组进行的,实际上同时是在拿患者作实验。中医的标准是上工,真正达标的医生很少。西医是以下工为标准,只要能够与整体相应就算合格。

中医是在进行治疗,西医是在进行实验。因为大多数中医不能真正代表中医,所以中西医之间其实一直没有机会进行真正的整体比较。个案相比,西医明显不敌,治疗结果相差悬殊。整体对比,中医又似乎处于劣势,统计结果无法验证。

从经营上看,中医是个体经营,西医是集体经营。中医是小农生产方式,西医是工业生产方式。两者的结果表现在规模与效果上(如所造成的污染)存在差异,两种结果的区别在于,前种方式更能够对作为个体的患者有利,后种方式更能够对作为集体的医生有利。所以,从治疗的效果看,中医是胜利者,而从经营的结果上看,西医是胜利者。其区别的本质表现在目的性上是,一个是以服务为根本目的,一个是以盈利为根本目的。一个是福利性质的,一个是商业性质的(至少目前在国内是这样表现的)。

但这些其实还不是最根本的区别,二者最根本的区别在于,真正能代表两种医学的治疗结果(权威的水平)的疗效的性质,即标本的差别,也即预后的情况。是真正的治愈了,还是只是掩盖一时,比如激素的短期效果与后期副作用。这种区别才是两种医学理论所指导下的医学实践的本质区别,而不是人为造成的错误之间的区别。

注:所谓权威的水平,指的是医术,而非资格或资历。当然,作为整体运作的西医之间的个体差异是不大的,就像机器的零部件一样,只存在合格与不合格的差别,是不太分别精品和次品的。

时间过得真快,还没感觉就两个多星期过去了。
在家歇了半年,现在渐渐的找到了以前的感觉。
退步了不少,思维也变慢了。
知识也变弱了。
要更多练习才行。
大家都进步了,感觉好不爽,努力学习,天天向上。
手里有这么多资料,要好好利用,要做国内最好的游戏团队。
加油!!

民主法治?为什么我没有投过票? 为什么贪官这么多?
公平正义?为什么贫富差距越来越大?为什么从没见过见义永为?
诚信友爱?为什么看到都是满街奸商?为什么看不到给老人让座?
充满活力?为什么火车站那么多乞丐? 为什么那么多人没钱看病?
安定有序?为什么杀人抢劫不断?为什么天天堵车?
人与自然和谐相处?为什么绿化面积在减小?



以上是个人观点与博客园无关。
看来要把博客移到国外去了。

本人做软件多年,一直与软件开发行业的各种级别的软件开发人才打交道,很多时候,

  还扮演面视考官的角色(很遗憾,本人还没有被面试过)。

  写下这篇文章,目的是区分各种层次的软件开发人员,也让软件开发人员能够对照自己,看看自己在什么层次。

  软件开发工作,其实是一种很复杂的工作,需要多方面的技能。我认为,尤其以学习能力和创新能力为主。所以,我以下对软件人才的层次划分,也围绕这两个能力展开。

  一、门外汉型:几乎没有学习能力,更没有创新能力。比如,买了一本《一步一步跟我学VB编程》之类的书,对照书上写的,把例子程序给做出来了,还把例子程序的某些窗口标题给修改了一下。然后,就自认为自己可以做软件开发工作了。到处递简历,应聘的职位为软件开发工程师。这类人,以刚毕业的计算机专业的大学生为多(当然,刚毕业的学生中也有非常高级的人才)。读书期间,就以玩游戏为主,考试的时候,就搞点舞弊过关。

  二、入门型:该类型的人员(不叫人才,所以叫人员),可能入门某一种到两种开发语言,10年前,我上大学的时候,这类人的典型特点是热衷于DOS命令的n种用法。比如,dir命令的各种参数。学习过basic语言,知道C语言中printf函数的各种参数的用法,到了2005年,这类人是热衷于windows下的注册表,热种于在自己的机器上安装各种开发工具(VB,VC,dephi,asp等)。但是,仅仅停留在编译开发工具中自带的几个例子程序中。(可能还会做点修改)。经过一段时间的学习,可能还自己能够编写个简单的windows应用程序,修改注册表的程序等等。其很多时间还是在玩游戏,上QQ聊天泡MM,看了一篇如何修改某病毒的文章,一定会对照文章上的说明,把病毒给修改了,然后到处发,以显示自己的能力。当然,很多时候,该类人即使对照文章的说明,也不能将病毒修改。那就找那些带配置工具的黑客程序去弄吧,比如。BO等就是他们最常用来炫耀的。中国的破解者与初级黑客,绝大部分是这一类人。懂的不多,还喜欢炫耀(为炫耀目的的破解和修改病毒就是这一类人的最大特点)。该类人员,一般都没有在软件公司从事软件开发工作。

  三、基本型人才:该类型一般是大学毕业,并且从事软件开发工作超过2年的人为多,至少比较熟悉一门语言(以VB,dephi,java,asp等其中的一种)。也有少数人熟悉C或者C++,但是如果是C或者C++,一般对指针等概念还是似懂非懂的状态。哦,对了,该类人员可能还会在自己的机器上安装过linux或者sco unix等。但由于对自己没有信心,大部分人会在半个月之后把linux删除。该类型人才,有一定学习能力。创新能力为零。适合培养成为软件蓝领,如果人际交往能力还可以的话,可以培养成为一个初级营销人员。该类型的人典型的特点是:你要他做个项目,他首先就会问:用什么语言?(因为用他不熟悉的语言对他来说,他就没有信心),该类人员,习惯看中文文档,不得以的情况下,才会看英文文档。另外,该类人员,喜欢购买软件开发类的书籍。该类人员,一般在软件公司从事软件开发工作,待遇在4000元到10000元以下为主。

  四、熟练工:该类型一般是毕业5年并一直从事软件开发工作,至少熟悉 VB,asp ,熟悉数据库,知道什么叫存储过程,什么叫触发器。知道软件工程管理的基本概念,如果做面象对象开发,可能还会用到Rose等工具。有过20人以下软件项目管理的经验。对于linux,至少知道是个开源的项目。由于做过比较大的软件项目,项目中带的小兵一般都不具备unix下的开发经验,所以,项目中难免会出现需要在unix下运行的代码,所以,就自己动手。用c编写过几段Unix下的小程序。学习能力比较强,该类人员,已经习惯看英文文档,有时候看翻译的别扭的中文文档会觉得不爽。干脆就找英文文档。该类人员,是否喜欢买书不得而知,如果喜欢买书,一般以非软件开发类书籍为主了。在技术选型方面具备一定的创新能力,至少,你叫他做一个报表程序,他会考虑用Excel的COM对象来实现。国内软件公司中的项目经理,绝大部分是这一类型的人才。待遇一般在6000到15000元左右。

  五、聪明型:该类人员的工作经历不重要,可以是还没毕业的学生,也可以是工作了10年的老鸟,1周内(甚至一小时)就熟悉了一门语言,并且可以开始用该语言开发,该类人员,由于学习能力很强,短时间内就熟悉了许多语言,即使从来没用过该语言,也敢于在该语言上进行软件开发,选择什么样的语言,不在于学没学过,而在于是否适合解决当前问题。对技术充满好奇与激情,举个例子,如果该类人员接触过linux,马上就会被Linux的魅力所吸引。即使与自己的工作无关,也会一回家就研究linux,可以肯定的是,该类人员的笔记本电脑上,肯定安装有linux ,并且,linux的启动次数和windows的启动次数一样多甚至更多。如果该类人员接触到了人工智能,至少会编写一个推理机程序来用用。另外,该类型人才的典型特点是学习能力超强。英语不一定很厉害,但是,不害怕看英文资料。该类型人才,许多并不是计算机专业毕业,可以是学数学的,物理的,音乐的等等都有可能。我就见过一个学英语的学生属于这种类型。该类型的人才,几乎所有的病毒代码是他们写出来的(不算那些修改病毒代码的人)。爱表现,也是他们的特点。如果该类人员在读书,那么,他们是软件公司青睐的人才,绝对不会出现简历递出三份还没有人要的情况,一旦进入公司,在半年内,其才能一定会得到公司领导的认可,并作为重点培养对象。为了留住这样的人才,软件公司一般会每听说有别的公司要挖他的消息就会给他涨工资一次。薪水的增长速度往往令同事红眼。

  六、技术天才型:该类人才,技术方面一流,如果只从技术方面的学习能力,创新能力来讲,都要超过以上的任何一种类型的人才。上帝造人总是很公平的,他们在技术方面是天才,往往其他方面几乎白痴,不善与人交往,甚至害怕与人交往。另外,某些东西对他们有致命吸引力,比如,有些人就迷恋自己做一个操作系统,有些人就迷恋人工智能。该类人员,不写软件则以,一写,肯定是一流的。全球一流。从语言来讲,因为他们几乎不用微软的开发工具做具体的项目,他们所看的技术资料,全部是英文资料,在网上交流的,全是操英语或者法语的人。即使是中国人,他们也习惯用英语与别人进行技术沟通。该类人才,如果在工作,一般是在某实验室,或者是在某基金的资助下开展研究,如果在软件公司,一定是主持举世瞩目的软件项目。或者,在自己开的小公司既当CEO又当CTO。由于其技术的优势明显,即使他不是一个很称职的CEO,也能让这个公司维持下去。

  七、数学家型:该类型人才,也许根本就不懂具体某种语言的开发(也可以懂),整天就研究算法。建模。一般不属于计算机专业。他们要把自己的成果变成现实,往往习惯找聪明型或者天才型人才帮他们实现。该类人员,因为不学计算机,所以,无法描述他们在学习技术方面的能力,但是,创新能力绝对一流。该类人才,没有在软件公司工作的,当然,如果其成果有一定商业价值,他们会成为某软件公司的顾问。或者干脆在某软件公司的实验室中当个主任什么的。

  八、比尔型:因为比尔的影响力巨大,所以,我们把具有一定软件开发能力,又有很强的商业运作能力的人归到这一类。比尔型人才,学习能力,在聪明型之上,在技术天才型之下。由于起社会知识面非常广泛,所以,知道什么软件能赚钱,怎么样做能赚钱。该类人写软件的目的只有一个,那就是赚钱,而不会太在乎采用什么样的技术。他们写软件,会极力迎合用户,迎合市场。

  对人的划分,有时候是很难的,有的人是跨类型的。但是,缺少创造的人,最多就到达熟练工型,具有超强创造力的人,可以达到技术天才型和数学家型,如果还有商业头脑,成为比尔型也是可能。最后一句话,如果你连足够的学习能力都没有,那么,就请你离开软件开发行业,另谋出路比较合适。

  这篇帖子,我首发在共享软件论坛,我认为,如果你不具备超强的学习能力,基本的创新能力和基本的商业能力,那么,就请你尽早不要做共享软件。

王国维---
古今之成大事业大学问者,必经过三种之境界:
“昨夜西风雕碧树,独上高楼,望尽天涯路。”此第一境也。
(注解:1。看清道路;2。说的是寻找“对象”。)
“衣带渐宽终不悔,为伊消得人憔悴。”此第二境也。
(注解:1。明确目标,重塑自我。执着,一往无前。2。说的是“死缠烂打”(男生追女生的惯用伎俩)。

“众里寻她千百度,回头蓦见,那人正在,灯火阑珊处。”此第三境也。
(注解:1。找回自我,圣人的境界。2。说的是“有情人终成眷属”。:))


以下是我从别处得来,然后按我的认知而思考,按我的经历而感悟,整理的10条信念,
很多道理大家比我更清楚,更有感悟些,只是我整理出来而已,个人见解,自然有片面、浅薄或误谬的地方,:)
有错有对,大家觉得对的,望大家共勉之:)
其实信念说起来容易,做起来也难:),但做时可以尽量往这些信条上靠近:)

事,说起来容易,做起来难
做技术容易,做人难;发展自己,做人尤为重要!
做人 = 丰富的知识
有能力,有做人原则,不看别人脸色;否则,只能微微侍从,处于被动。

理论与实际很有一段距离;至少计算机理论与实际开发应用技术是这样的:)
中国的教育很失败,孩子的成功教育,50%来自家庭教育,20%来自于你身边的人,30%来自学校的照本宣课教育
理想与现实有很大差距;
失败和成功取决于一个人的意志
成功 = 使自己成为最好的自己。当然,这里的“最好”,也是自己的标准。

1.人生的价值,在坚持不懈地努力学习中显现;不要追求完美,人生不可能有完美;

2.只有多读书,才能不断扩大知识面,人的知识面愈广博,视野愈开阔,
人的表达、社交能力也愈强,也愈加自信,人的各方面也愈臻完美。


3.知道如何停止的人才知道如何加快速度。

4.自助者,天助。
在你失败或处于困境时,能够帮助你,使你重新获得希望,重新看到光明的,只有你自己!
天助强者。

5.在任何处境中,都要保持着平静乐观的心态,保持着幽默。
只有热情和激情,才能赢得积极的人生和快乐的生活。
过分的生气或愤怒,不但于事无补,反而可能也会使事情或处境变得更糟


6.任何事情的发生,都有其必然的原因.
任何事情都没有绝对,塞翁失马焉知非福!

7.快乐不是因为你拥有多少,而是你计较多少!
不改变改变不了的,改变必须改变的。
知足者常乐;知足有时,也是懒惰、不努力的借口。
你能找到痛苦的借口,也会找到快乐的理由。


8.男人应该要有宽阔的胸襟,不要为了点点面子、虚荣和得失,生气或愤怒;
大地之博,承载万物,男人应像大地一样,用宽阔的胸襟、坚毅的品格承载一
切.

9.严于纪己,宽于待人。学会欣赏别人。
每个人的处境和经历不一样,人自然有强弱之分,不要小瞧弱者,在强者面前也不要看轻自己;
命,先天因素,无法改变
运,机遇缘分,要靠自己努力和争取

10.生命是一种过程。人生没有彩排,每天都是现场直播。
珍惜你的朋友,以及你身边每个人,珍惜每次聚会,因为你所经历的每次场景都不会重现。
人活着,要珍惜每一天,要快乐,因为每个人将会死得很久很久:)

 

双拳难敌四手,同样,一手难敌两手。玩魔兽,只用右手是没有用,我们还要学会用左手------键盘。
键盘操作相对于鼠标操作,更加快捷、方便、准确。我先从基础操作讲起,然后是进阶操作,再是更精细的操作。其他的就没有了,因为本人的水平只能到这里了,呵呵。

从基础说起:

一:基础操作:用键盘制造单位,释放魔法,使用物品。
  魔兽中的一切东西都可以用快捷键来完成,而鼠标只是起到一个定位的作用。比如,暗夜做小精灵,你可以用鼠标点击基地里精灵的头像,也可以直接按w;或者暗夜做月亮井,你可以选中小精灵,点建造,再点月亮井头像,也可以直接按b,m。具体的快捷键,你可以把鼠标移到具体单位的头像上,鼠标会弹出一些字幕,单位名称后面括号内的黄色字母,就是制造这个单位的快捷键。做到制作单位和建造建筑用键盘来完成,是操作的基础。
  重要的一点,魔兽里面,所有的魔法也同样可以用快捷键来完成。这就意味着你可以用键盘迅速的完成英雄魔法的释放。比如,人族的山岳放锤子,你可以用鼠标点击锤子的图标,再点击对方的英雄,也可以键盘按t,同时鼠标点中对方的英雄。魔法释放的速度也许就相差半秒或者1秒钟。但有时候,这半秒钟或者1秒钟就决定着比赛的胜负。
同样,在商店购买物品,也可以点击商店然后按下物品相应的快捷键。这样可以让你的英雄在靠近商店作战的过程中,迅速的购买物品(回程,血瓶,无敌,群疗或者飞艇),以很好的保护自己以及部队。
  同样,英雄物品的使用也可以用键盘来完成。物品栏对应的是数字键盘上前两竖排的按键。就是说,第一个物品可以按7来使用,第二个物品可以按8来使用,第三个物品按4来使用,以此类推。物品使用的快捷键也许有人觉得使用起来,还不如用鼠标来的快。但用键盘使用物品有些好处:1,使用数量类物品(例如药膏,飓风权仗),鼠标的点击显得烦琐,键盘使用更加快捷。2,在中后期混战中,很可能出现的情况就是你的英雄身上明明有血瓶或者无敌,但是用鼠标使用时出现点偏,误点而导致英雄的阵亡,而用键盘使用失误率更低。用键盘使用物品重要的一点在于,尽量把要使用的物品(例如血瓶,无敌,回程)放在靠物品栏左边一侧,毕竟按7,4,1比按8,5,2要好得多。
  另外,永远记住F1是你的首发英雄,F2是你的次发英雄,F3是你的三发英雄。这3个键可以让你迅速的选中你想要选中的英雄,在混乱的战斗中了解他们的位置。
一些你可能不知道的热键:
1,“~”,按它可以选中正在休息的农民。
2,“backspace”,按它可以迅速的切回主基地,并以主基地为屏幕的中心。这个热键在英雄回程救援的时候极为重要,你选中英雄,使用回程,再按backspace切回基地,选中自己回程的理想地点,回程(别忘了回程可以选择位置,不一定要点到主基地上才能回来)。这样总比在小地图上点击基地再选好位置要快一点。
3,insert和delete可以让屏幕右旋或者左旋,这样你可以点到一些正常视角点击不到的单位,比如人族探路的小动物往往躲在高大建筑的后面。
4,pageup和pagedown可以让视角下移或者上移,鼠标中键也可以做到。这样你可以近距离欣赏到你想看到的东西。
5,O键可以给英雄迅速的学习技能,做法是选中英雄,按O再按相应技能的快捷键,相当于鼠标点击那个“+”号。例如你的死亡骑士在红血的时候恰好升级,可以迅速的按下O、E学习死亡契约,再吃自己的单位,保证死亡骑士不死。
用键盘建造、放魔法、用物品,重要的一点在于摈弃以前用鼠标点击的坏习惯,强迫自己使用键盘。不断的使用着键盘以后,你会发现键盘的使用,已经成为了你的习惯,而且终会尝到使用键盘的甜头。
PS:A键,H键,P键,tab键的运用。
1,A键,攻击键。如果只用右键行军,部队只是移动到目的地,再进行攻击。而使用A键然后点目的地行军,部队行进过程中如果发现敌军,立刻能够停下攻击。另外如果你想杀掉自己或者队友的单位,同样是用A键攻击。
2:H键,保持原位键。例如对手的基地里海了箭塔,而你只能用攻城车攻击他的基地,你的对手往往会用几个单位出来诱引你的单位到他的箭塔群里去。这个时候你可以把你的非攻城单位用H键停留原位保护攻城车。
3:P键,巡逻键。例如你非要让不死的阴影在对手的主基地与分基地之间转来转去,可以先让阴影到主基地,按p再点分基地,你的阴影就会达到你的目的了。
4:TAB键,子组转换键。例如把死亡骑士和巫妖编入一个组队,而我想释放巫妖的霜冻新星。可以按tab,就发现状态栏里巫妖的头像凸现了出来,就可以释放霜冻新星了。

二:进阶的操作:alt、shift、ctrl的使用。
可以说,不使用这3个键的魔兽玩家基本没有入门,不掌握这3个键的魔兽玩家不能算是高手。个人认为,掌握这3个键的过程,是菜鸟成为高手的必由之路。下面介绍一下这3个键的作用。

㈠alt键:
①:按alt键的用途是观察屏幕上所有单位的血量。按下alt之后你可以发现每一个单位头顶上都出现血条,这使得你对敌我双方,哪个单位濒死一目了然。然后你应该做的是把自己濒死的单位向后拖动,然后想办法把对方濒死的单位弄死。记住操作的最终目的,尽可能多的保护自己的每一个单位,尽可能多的杀死对方的每一个单位。据说某高手在战斗的时候,是把一根牙签插在alt键上的。虽然略觉夸张,但这事仍然说明alt键事关重大。
②:alt键可以和其他键组合产生作用,最著名的莫过于alt+ctrl+del了,其次是alt+F4。但这些组合在魔兽过程中是不能乱按的。在魔兽中常用的组合是:
1,alt+G 在2vs2的时候很重要,用于在地图上发出一个警告。可以告诉你的盟友你在哪里需要帮助。
2,alt+A 改变自己、队友、敌人的颜色。尽量改变成模式3,即自己成为蓝色,队友成为绿色,敌人成为红色。以在战斗时能更加分清敌我,以免误伤。
3,alt+F 开关队型移动。在逃跑的时候,记住一定要把队型移动关掉,否者那些远程单位非要等到近战单位逃到前面才肯移动。

㈡shift键:
①:shift键的一个作用其实很简单,说白了就是让一个单位连续的做几件事。但这个作用一旦运用起来,就变得很有用处了。
1,让一个农民做完建筑之后自动回去采矿。做法是选中农民,下达建造命令以后按住shift,再用右键点击木头,或者金矿。
2,让一个农民连续做几样建筑。做法是选中农民,下达第一个建造命令,按住shift,下达第二个建造命令...类推。结合第1种方法,可以让农民做完一大堆建筑以后继续回去采矿。如果连续建造的是相同的建筑,比如人族的农场。你可以先把农民拖出,按住shift不放,按BF(农场快捷键),之后想做哪里就做哪里,往空地按就是,最后别忘了用shift把农民拉回来采矿。
3,连续向几个地方探路。做法是选中探路的单位,先点击第一个探路地点,按住shift不放,再依次点击你想让这个单位去的各个地方,放开shift。
4,让你的单位集中火力,连续攻击N个对方单位。这种做法的对象最好是远程单位。做法是用右键点击对方的一个单位,按shift连续点击你依次想攻击的单位。这样可以集中火力,造成对某几个单位的连续高伤害。但这种做法的弊端在于如果对方把正在被攻击的单位调开,你的单位仍然会继续追击,这样会受到更多对方其他单位的攻击。所以最好只是连续的点射2-3个单位就可以了。因为如果你一下下达点射12个单位的指令,一旦对手把他的单位调开,你又要重新下达新的指令。汗,你累不累啊。
5,让你的部队绕过野生怪物。经常战斗中出现的情况是你的单位集结在英雄身上,而在白天生产出来的单位往往要经过野生怪物的旁边,造成单位的受伤或者死亡。避免这种情况的发生可以使用shift键。做法:点击兵营,按住shift设置集结点,把集结点绕开野生怪物,最后点在英雄身上。之后,从兵营出来的单位会在N个集结点上先后走过,最后走到英雄身上。
6,骚扰之后全身而退。例如石像鬼骚扰,先点杀一个农民(或几个),再shift点击安全的地方。
7,其他用途。具体的很多想不起来。觉得最经典的就是暗夜的熊,先按f变回德鲁伊,shift+e加血,再shift+f变回。这个操作用shift可以在一秒内完成,可是如果你等熊变回德鲁伊,再按e加血,等加血后再按f变回,2-3秒的时间都过去了。
②:在一个队伍里添加或者剔除单位。
1,添加。想要把一个单位编入你正在控制的这个队伍,只要按shift在点击(框选也可以)想添加的单位就可以了。这个做法在编入刚制造出来的单位时尤其重要。
2,剔除。想要把一个单位剔除你正在控制的这个队伍,只要按shift在点击(框选也可以)想剔除的单位就可以了。
具体实例,在losttemple上,你的4个兽兵有1个濒死,可以先把这4个兽兵右键点击生命之泉,再按shift点中濒死兽兵(状态栏的图标也可以),把这个兽兵从组队里剔除,再控制其他3个兽兵做其他的工作(mf,骚扰之类),等这个濒死的兽兵满血以后再把它添加到组队里来。

㈢ctrl键:
①:ctrl键的第一个作用用于组队。例如想把7个火枪手和2个男巫编成一队,只要选中7个火枪手和2个男巫,按ctrl+1,就算是把火枪手和男巫编成一队了。接下来,按一次1是选中1队,按两次1是选中1队,并且以1队做为屏幕中心。魔兽里面最多可以有0、1-9十个编队。把每一个单位编入组队,是操作的基础。另外,建筑也是可以被编队的。例如把兵营编为5队,可以一边在战斗或者mf,一边按5做步兵或者火枪。
②:选中屏幕内相同的单位。例如想选中同个屏幕中的8个食尸鬼,可以按住ctrl再点随便一个食尸鬼,就可以全部选中8个了。但选中的单位,最多只有12个,因为一个组队只能容纳12个单位嘛,呵呵。
③:ctrl键的另外一个作用是传说中的“子组顺序修改键”。进入游戏后,“选项”内的“游戏性”里,把“子组顺序修改键”前面的方框点上勾,就可以用上这个功能了。这个功能的作用可以将同一个组队的不同单位分开工作。举个例子,不死前期使用骷髅权仗+食尸鬼mf,把食尸鬼和骷髅编在一个组队,而mf的时候我想把骷髅顶在前面,就可以先按TAB(因为骷髅的优先度比食尸鬼低)选中骷髅,按住ctrl移动到前面。你会发现只有骷髅在移动而食尸鬼是不会动的。

三:更精细的操作:M键,S键的使用。

㈠M键:本意是move,但是我们可以把它引申为包围。对,它就是传说中的包围键。要成为高手,就要把包围练到神乎其技。各位,努力了。
战场上的第一焦点永远是英雄,所以我们当然先说的是包围英雄。理论上,在没有地形的影响下,4个单位就能够把一个英雄围住。但是这种情况很少出现,所以我们一般用5个或5个以上的单位来围英雄。
围英雄基本的操作步骤(用6食尸鬼为例):1,先用右键移动食尸鬼到对方英雄的另外一边。2,当有2个食尸鬼超过了英雄之后,选中6食尸鬼,M到对方英雄身上。3,再按M,再点到对方英雄身上。4,再按M,再点到对方英雄身上。5,按A攻击对方英雄。包围时候最重要的一点,永远不要认为一次M键就可以把对方围住。[{当然,包围以后要注意再用A建进行攻击,HOHO,别忘记了哦。}]
然而如此明显的包围,对手很容易察觉,从而很轻松的跑掉。所以我们总是想尽办法来相对的减缓对方英雄的速度,来实施更轻松的包围。做法有:
1,固定对方英雄:山岳的风暴锤,牛头人酋长的战争践踏,萨满的净化,狼骑的诱捕,巫医的静止陷阱,丛林守护者的树根缠绕,猛禽德鲁伊的飓风,地穴领主的穿刺,恐惧魔王的睡眠和终极技能,地精修理匠的飞弹。
2,缓慢对方英雄:血法的虚无,女巫的缓慢,影子猎手的巫术,飞龙的浸毒攻击,守望者的暗影突袭(毒镖),树妖的毒素攻击,巫妖的霜冻新星,不死的霜冻塔,骷髅法师的残废,冰龙的攻击,哪伽的冰箭,熊猫的酒雾。当然,还有佩带了闪电球、毒液球或者霜冻球的英雄。
3,加快自己部队:兽族的加速卷轴,牛头人酋长的耐久光环,死亡骑士的邪恶光环(包括拥有天灾骨钟的英雄)。
还有一种做法就是利用地形。论坛上的一张恶魔猎手被一个月亮井和3个小弓箭手包围的图文战报相信大家都看过了,这是利用地形的一次经典包围。同样,我们也可以利用地图上的拐角,楼梯用更少的兵包围英雄。这就要让对手的英雄尽量的走旁边。举个例子,我们可以把自己基地的建筑只留最边上一个口子,假如对方的英雄要来骚扰,一定只能从建筑和树林的缝隙中进来,而我们可以利用建筑和树林,实施包围。
利用召唤单位包围也是一种好方法,具体怎么搞我还真不知道(众人倒:“你个菜鸟,不知道你说什么啊!”)。在战斗的时候,用3个兽兵先包围住你的一半,然后先知躲在一旁一放狼,英雄就正好被包围了。另外死亡之书,一下是召唤出8个单位,围一个英雄足够。这两种情况都是我在和别人对战时候遇到过的尴尬情况。当然我还有在骚扰人族开分基地时候,被民兵+水元素包围的情况,555~~~。
M键还可以用来反包围。当你的对手用固定或者减缓你英雄的方法想对你英雄实施包围,这个时候你可以把自己的单位包围英雄,然后在英雄恢复之后逃离包围。
包围普通的单位和包围英雄基本上是一样的,只是有些单位的体积比英雄小一点,包围的时候需要更多的单位。
一次成功的包围往往可以左右一场战斗的胜负。例如你的对手大军浩浩荡荡的开到你家来,而你家里只有一点点的兵力可守。如果包围对手英雄成功,既可以解决你的燃眉之急,又浪费了对手的一张¥350的回程。
在越来越多的人懂得把濒死的兵拖动以保护单位的现在,好好的练习包围吧。

㈡S键:本意是stop,但是我们可以把它引申为阻挡。
阻挡一个单位的基本做法是:1,让你的单位想办法跑到它移动路线的前面。2,把你的单位斜插到它的移动路线上。3,一旦走到它要移动的路线上面,按S。
接下来你要做的就是不停的推测它的移动路线,不停的占据它的移动路线,一边用鼠标控制你的单位的移动路线,一边狂按S。阻挡时候最重要的一点,永远不要以为你的单位能够恰好跑到它的移动路线上去阻挡它,要用S键控制你的单位在恰当的位置停下来,并用鼠标右键让你的单位继续移动。
有时候我认为,阻挡几乎和包围相同的重要。你的对手在觉得打不赢之后,往往控制大量黄血或者红血的单位逃跑。而你完全可以用一个或者几个单位阻挡住对手一个或几个单位,而等待自己的英雄过来释放魔法或者等待自己的单位过来包围。给我印象最深的两个阻挡,一个是一个人族用农民阻挡一个红血的5级先知,然后这个先知被大法师丢下4个火球而死,还有一个是xiaOt用2条3级隐形狼阻挡一个黄血的6级大法师,然后这个大法师愣是被2道闪电+2个震荡波打倒。
当然,S键的阻挡也可以用来掩护自己部队的撤退。当自己撤退而对手穷追不舍得时候,我们可以让一个速度快一点的单位(这样在掩护这个单位可以迅速的逃走),例如英雄、女猎手、狼骑士之类,阻挡对手部队,让他停止对你的追击,当然最重要的还是意识了。

最后祝大家每次都以一个快乐的心情去面对每一场比赛。

1.求下面函数的返回值(微软)


int func(x)
{
   int countx = 0;
   while(x)
   {
         countx ++;
         x = x&(x-1);
    }
   return countx;
}  

假定x = 9999。 答案:8

思路:将x转化为2进制,看含有的1的个数。

2. 什么是“引用”?申明和使用“引用”要注意哪些问题?

答:引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。申明一个引用的时候,切记要对其进行初始化。引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的引用。

3. 将“引用”作为函数参数有哪些特点?

(1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。

(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。

(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。

4. 在什么时候需要使用“常引用”? 

如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。常引用声明方式:const 类型标识符 &引用名=目标变量名;

例1

int a ;
const int &ra=a;
ra=1; //错误
a=1; //正确

例2

string foo( );
void bar(string & s);

那么下面的表达式将是非法的:

bar(foo( ));
bar("hello world");

原因在于foo( )和"hello world"串都会产生一个临时对象,而在C++中,这些临时对象都是const类型的。因此上面的表达式就是试图将一个const类型的对象转换为非const类型,这是非法的。

引用型参数应该在能被定义为const的情况下,尽量定义为const 。

5. 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?

格式:类型标识符 &函数名(形参列表及类型说明){ //函数体 }

好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error!

注意事项:

(1)不能返回局部变量的引用。这条可以参照Effective C++[1]的Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。

(2)不能返回函数内部new分配的内存的引用。这条可以参照Effective C++[1]的Item 31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。

(3)可以返回类成员的引用,但最好是const。这条原则可以参照Effective C++[1]的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。

(4)流操作符重载返回值申明为“引用”的作用:

流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << "hello" << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受。对于返回一个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧。 赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。

例3

#i nclude
int &put(int n);
int vals[10];
int error=-1;
void main()
{
put(0)=10; //以put(0)函数值作为左值,等价于vals[0]=10;
put(9)=20; //以put(9)函数值作为左值,等价于vals[9]=20;
cout<cout<}
int &put(int n)
{
if (n>=0 && n<=9 ) return vals[n];
else { cout<<"subscript error"; return error; }
}

(5)在另外的一些操作符中,却千万不能返回引用:+-*/ 四则运算符。它们不能返回引用,Effective C++[1]的Item23详细的讨论了这个问题。主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new分配的对象的引用、返回一个静态对象引用。根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。静态对象的引用又因为((a+b) == (c+d))会永远为true而导致错误。所以可选的只剩下返回一个对象了。

6. “引用”与多态的关系?

引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。

例4

Class A; Class B : Class A{...};  B b; A& ref = b;

7. “引用”与指针的区别是什么?

指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。此外,就是上面提到的对函数传ref和pointer的区别。

8. 什么时候需要“引用”?

流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。

以上 2-8 参考:http://blog.csdn.net/wfwd/archive/2006/05/30/763551.aspx

9. 结构与联合有和区别?
1. 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。
2. 对于联合的不同成员赋值, 将会对其它成员重写,  原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的。

10. 下面关于“联合”的题目的输出?

a)

#i nclude
union
{
int i;
char x[2];
}a;


void main()
{
a.x[0] = 10;
a.x[1] = 1;
printf("%d",a.i);
}
答案:266 (低位低地址,高位高地址,内存占用情况是Ox010A)

b)

    main()
    {
         union{                   /*定义一个联合*/
              int i;
              struct{             /*在联合中定义一个结构*/
                   char first;
                   char second;
              }half;
         }number;
         number.i=0x4241;         /*联合成员赋值*/
         printf("%c%c\n", number.half.first, mumber.half.second);
         number.half.first='a';   /*联合中结构成员赋值*/
         number.half.second='b';
         printf("%x\n", number.i);
         getch();
    }
答案: AB   (0x41对应'A',是低位;Ox42对应'B',是高位)

      6261 (number.i和number.half共用一块地址空间)

11. 已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数,请编写函数 strcpy。


答案:
char *strcpy(char *strDest, const char *strSrc)
{
if ( strDest == NULL || strSrc == NULL)
return NULL ;
if ( strDest == strSrc)
return strDest ;
char *tempptr = strDest ;
while( (*strDest++ = *strSrc++) != ‘\0’)
;
return tempptr ;
}

12. 已知String类定义如下:

class String
{
public:
String(const char *str = NULL); // 通用构造函数
String(const String &another); // 拷贝构造函数
~ String(); // 析构函数
String & operater =(const String &rhs); // 赋值函数
private:
char *m_data; // 用于保存字符串
};

尝试写出类的成员函数实现。

答案:

String::String(const char *str)
{
  if ( str == NULL ) //strlen在参数为NULL时会抛异常才会有这步判断
    {
      m_data = new char[1] ;
      m_data[0] = '\0' ;
    }
  else
   {
      m_data = new char[strlen(str) + 1];
      strcpy(m_data,str);
   }

}

String::String(const String &another)
{
   m_data = new char[strlen(another.m_data) + 1];
   strcpy(m_data,other.m_data);
}


String& String::operator =(const String &rhs)
{
   if ( this == &rhs)
       return *this ;
   delete []m_data; //删除原来的数据,新开一块内存
   m_data = new char[strlen(rhs.m_data) + 1];
   strcpy(m_data,rhs.m_data);
   return *this ;
}


String::~String()
{
   delete []m_data ;
}

13. .h头文件中的ifndef/define/endif 的作用?

答:防止该头文件被重复引用。

14. #i nclude 与 #i nclude "file.h"的区别?

答:前者是从Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h。

15.在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?

首先,作为extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。

通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数

extern "C"是连接申明(linkage declaration),被extern "C"修饰的变量和函数是按照C语言方式编译和连接的,来看看C++中对类似C的函数是怎样编译的:

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:

void foo( int x, int y );
  

该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。

_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。

同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

未加extern "C"声明时的连接方式

假设在C++中,模块A的头文件如下:

// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif  

在模块B中引用该函数:

// 模块B实现文件 moduleB.cpp
#i nclude "moduleA.h"
foo(2,3);
  

实际上,在连接阶段,连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!

加extern "C"声明后的编译和连接方式

加extern "C"声明后,模块A的头文件变为:

// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y );
#endif  

在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:
(1)模块A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;

(2)连接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。

如果在模块A中函数声明了foo为extern "C"类型,而模块B中包含的是extern int foo( int x, int y ) ,则模块B找不到模块A中的函数;反之亦然。

所以,可以用一句话概括extern “C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这个语言是怎么做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题):实现C++与C及其它语言的混合编程。  

明白了C++中extern "C"的设立动机,我们下面来具体分析extern "C"通常的使用技巧:

extern "C"的惯用法

(1)在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:

extern "C"
{
#i nclude "cExample.h"
}

而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。

C++引用C函数例子工程中包含的三个文件的源代码如下:

/* c语言头文件:cExample.h */
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x,int y);
#endif


/* c语言实现文件:cExample.c */
#i nclude "cExample.h"
int add( int x, int y )
{
return x + y;
}


// c++实现文件,调用add:cppFile.cpp
extern "C"
{
#i nclude "cExample.h"
}
int main(int argc, char* argv[])
{
add(2,3);
return 0;
}

如果C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern "C" { }。


(2)在C中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C语言中不能直接引用声明了extern "C"的该头文件,应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。

C引用C++函数例子工程中包含的三个文件的源代码如下:

//C++头文件 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif


//C++实现文件 cppExample.cpp
#i nclude "cppExample.h"
int add( int x, int y )
{
return x + y;
}


/* C实现文件 cFile.c
/* 这样会编译出错:#i nclude "cExample.h" */
extern int add( int x, int y );
int main( int argc, char* argv[] )
{
add( 2, 3 );
return 0;
}

15题目的解答请参考《C++中extern “C”含义深层探索》注解:


16. 关联、聚合(Aggregation)以及组合(Composition)的区别?

涉及到UML中的一些概念:关联是表示两个类的一般性联系,比如“学生”和“老师”就是一种关联关系;聚合表示has-a的关系,是一种相对松散的关系,聚合类不需要对被聚合类负责,如下图所示,用空的菱形表示聚合关系:

                         

从实现的角度讲,聚合可以表示为:

class A {...}  class B { A* a; .....}

而组合表示contains-a的关系,关联性强于聚合:组合类与被组合类有相同的生命周期,组合类要对被组合类负责,采用实心的菱形表示组合关系:

                           

实现的形式是:

class A{...} class B{ A a; ...}

参考文章:http://blog.csdn.net/wfwd/archive/2006/05/30/763753.aspx

         http://blog.csdn.net/wfwd/archive/2006/05/30/763760.aspx

17.面向对象的三个基本特征,并简单叙述之?

1. 封装:将客观事物抽象成类,每个类对自身的数据和方法实行protection(private, protected,public)

2. 继承:广义的继承有三种实现形式:实现继承(指使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。前两种(类继承)和后一种(对象组合=>接口继承以及纯虚函数)构成了功能复用的两种方式。

3. 多态:是将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

18. 重载(overload)和重写(overried,有的书也叫做“覆盖”)的区别?

常考的题目。从定义上来说:

重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

重写:是指子类重新定义复类虚函数的方法。

从实现原理上来说:

重载:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;和function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!

重写:和多态真正相关。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚绑定)。

19. 多态的作用?

主要是两个:1. 隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重用;2. 接口重用:为了类在继承和派生的时候,保证使用家族中任一类的实例的某一属性时的正确调用。

20. Ado与Ado.net的相同与不同?

除了“能够让应用程序处理存储于DBMS 中的数据“这一基本相似点外,两者没有太多共同之处。但是Ado使用OLE DB 接口并基于微软的COM 技术,而ADO.NET 拥有自己的ADO.NET 接口并且基于微软的.NET 体系架构。众所周知.NET 体系不同于COM 体系,ADO.NET 接口也就完全不同于ADO和OLE DB 接口,这也就是说ADO.NET 和ADO是两种数据访问方式。ADO.net 提供对XML 的支持。

21. New delete 与malloc free 的联系与区别?
答案:都是在堆(heap)上进行动态的内存操作。用malloc函数需要指定内存分配的字节数并且不能初始化对象,new 会自动调用对象的构造函数。delete 会调用对象的destructor,而free 不会调用对象的destructor.

22. #define DOUBLE(x) x+x ,i = 5*DOUBLE(5); i 是多少?
答案:i 为30。

23. 有哪几种情况只能用intialization list 而不能用assignment?

答案:当类中含有const、reference 成员变量;基类的构造函数都需要初始化表。

24. C++是不是类型安全的?
答案:不是。两个不同类型的指针之间可以强制转换(用reinterpret cast)。C#是类型安全的。

25. main 函数执行以前,还会执行什么代码?
答案:全局对象的构造函数会在main 函数之前执行。

26. 描述内存分配方式以及它们的区别?
1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。
2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。
3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。

27.struct 和 class 的区别

答案:struct 的成员默认是公有的,而类的成员默认是私有的。struct 和 class 在其他方面是功能相当的。

从感情上讲,大多数的开发者感到类和结构有很大的差别。感觉上结构仅仅象一堆缺乏封装和功能的开放的内存位,而类就象活的并且可靠的社会成员,它有智能服务,有牢固的封装屏障和一个良好定义的接口。既然大多数人都这么认为,那么只有在你的类有很少的方法并且有公有数据(这种事情在良好设计的系统中是存在的!)时,你也许应该使用 struct 关键字,否则,你应该使用 class 关键字。  

28.当一个类A 中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释一下编译器为什么没有让它为零。(Autodesk)
答案:肯定不是零。举个反例,如果是零的话,声明一个class A[10]对象数组,而每一个对象占用的空间是零,这时就没办法区分A[0],A[1]…了。

29. 在8086 汇编下,逻辑地址和物理地址是怎样转换的?(Intel)
答案:通用寄存器给出的地址,是段内偏移地址,相应段寄存器地址*10H+通用寄存器内地址,就得到了真正要访问的地址。

30. 比较C++中的4种类型转换方式?

请参考:http://blog.csdn.net/wfwd/archive/2006/05/30/763785.aspx,重点是static_cast, dynamic_cast和reinterpret_cast的区别和应用。

31.分别写出BOOL,int,float,指针类型的变量a 与“零”的比较语句。
答案:
BOOL :    if ( !a ) or if(a)
int :     if ( a == 0)
float :   const EXPRESSION EXP = 0.000001
         if ( a < EXP && a >-EXP)
pointer : if ( a != NULL) or if(a == NULL)



32.请说出const与#define 相比,有何优点?
答案:1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
     2) 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。

33.简述数组与指针的区别?
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。
(1)修改内容上的差别
char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意p 指向常量字符串
p[0] = ‘X’; // 编译器不能发现该错误,运行时错误
(2) 用运算符sizeof 可以计算出数组的容量(字节数)。sizeof(p),p 为指针得到的是一个指针变量的字节数,而不是p 所指的内存容量。C++/C 语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
char a[] = "hello world";
char *p = a;
cout<< sizeof(a) << endl; // 12 字节
cout<< sizeof(p) << endl; // 4 字节
计算数组和指针的内存容量
void Func(char a[100])
{
cout<< sizeof(a) << endl; // 4 字节而不是100 字节
}

34.类成员函数的重载、覆盖和隐藏区别?
答案:
a.成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
b.覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
c.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

35. There are two int variables: a and b, don’t use “if”, “? :”, “switch”or other judgement statements, find out the biggest one of the two numbers.答案:( ( a + b ) + abs( a - b ) ) / 2

36. 如何打印出当前源文件的文件名以及源文件的当前行号?
答案:
cout << __FILE__ ;
cout<<__LINE__ ;
__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的。

37. main 主函数执行完毕后,是否可能会再执行一段代码,给出说明?
答案:可以,可以用_onexit 注册一个函数,它会在main 之后执行int fn1(void), fn2(void), fn3(void), fn4 (void);
void main( void )
{
String str("zhanglin");
_onexit( fn1 );
_onexit( fn2 );
_onexit( fn3 );
_onexit( fn4 );
printf( "This is executed first.\n" );
}
int fn1()
{
printf( "next.\n" );
return 0;
}
int fn2()
{
printf( "executed " );
return 0;
}
int fn3()
{
printf( "is " );
return 0;
}
int fn4()
{
printf( "This " );
return 0;
}
The _onexit function is passed the address of a function (func) to be called when the program terminates normally. Successive calls to _onexit create a register of functions that are executed in LIFO (last-in-first-out) order. The functions passed to _onexit cannot take parameters.


38. 如何判断一段程序是由C 编译程序还是由C++编译程序编译的?
答案:
#ifdef __cplusplus
cout<<"c++";
#else
cout<<"c";
#endif

39.文件中有一组整数,要求排序后输出到另一个文件中
答案:

#i nclude

#i nclude

using namespace std;


void Order(vector& data) //bubble sort
{
int count = data.size() ;
int tag = false ; // 设置是否需要继续冒泡的标志位
for ( int i = 0 ; i < count ; i++)
{
for ( int j = 0 ; j < count - i - 1 ; j++)
{
if ( data[j] > data[j+1])
{
tag = true ;
int temp = data[j] ;
data[j] = data[j+1] ;
data[j+1] = temp ;
}
}
if ( !tag )
break ;
}
}


void main( void )
{
vectordata;
ifstream in("c:\\data.txt");
if ( !in)
{
cout<<"file error!";
exit(1);
}
int temp;
while (!in.eof())
{
in>>temp;
data.push_back(temp);
}
in.close(); //关闭输入文件流
Order(data);
ofstream out("c:\\result.txt");
if ( !out)
{
cout<<"file error!";
exit(1);
}
for ( i = 0 ; i < data.size() ; i++)
out<40. 链表题:一个链表的结点结构
struct Node
{
int data ;
Node *next ;
};
typedef struct Node Node ;


(1)已知链表的头结点head,写一个函数把这个链表逆序 ( Intel)

Node * ReverseList(Node *head) //链表逆序
{
if ( head == NULL || head->next == NULL )
return head;
Node *p1 = head ;
Node *p2 = p1->next ;
Node *p3 = p2->next ;
p1->next = NULL ;
while ( p3 != NULL )
{
p2->next = p1 ;
p1 = p2 ;
p2 = p3 ;
p3 = p3->next ;
}
p2->next = p1 ;
head = p2 ;
return head ;
}
(2)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序。(保留所有结点,即便大小相同)
Node * Merge(Node *head1 , Node *head2)
{
if ( head1 == NULL)
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
Node *p1 = NULL;
Node *p2 = NULL;
if ( head1->data < head2->data )
{
head = head1 ;
p1 = head1->next;
p2 = head2 ;
}
else
{
head = head2 ;
p2 = head2->next ;
p1 = head1 ;
}
Node *pcurrent = head ;
while ( p1 != NULL && p2 != NULL)
{
if ( p1->data <= p2->data )
{
pcurrent->next = p1 ;
pcurrent = p1 ;
p1 = p1->next ;
}
else
{
pcurrent->next = p2 ;
pcurrent = p2 ;
p2 = p2->next ;
}
}
if ( p1 != NULL )
pcurrent->next = p1 ;
if ( p2 != NULL )
pcurrent->next = p2 ;
return head ;
}
(3)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序,这次要求用递归方法进行。 (Autodesk)
答案:
Node * MergeRecursive(Node *head1 , Node *head2)
{
if ( head1 == NULL )
return head2 ;
if ( head2 == NULL)
return head1 ;
Node *head = NULL ;
if ( head1->data < head2->data )
{
head = head1 ;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2 ;
head->next = MergeRecursive(head1,head2->next);
}
return head ;
}

41. 分析一下这段程序的输出 (Autodesk)
class B
{
public:
B()
{
cout<<"default constructor"<}
~B()
{
cout<<"destructed"<}
B(int i):data(i)    //B(int) works as a converter ( int -> instance of  B)
{
cout<<"constructed by parameter " << data <}
private:
int data;
};


B Play( B b)
{
return b ;
}

(1)                                            results:
int main(int argc, char* argv[])      constructed by parameter 5
{                                     destructed  B(5)形参析构
B t1 = Play(5); B t2 = Play(t1);     destructed  t1形参析构
return 0;               destructed  t2 注意顺序!
}                                     destructed  t1

(2)                                   results:
int main(int argc, char* argv[])      constructed by parameter 5
{                                     destructed  B(5)形参析构
B t1 = Play(5); B t2 = Play(10);     constructed by parameter 10
return 0;               destructed  B(10)形参析构
}                                     destructed  t2 注意顺序!

                                     destructed  t1

42. 写一个函数找出一个整数数组中,第二大的数 (microsoft)
答案:
const int MINNUMBER = -32767 ;
int find_sec_max( int data[] , int count)
{
int maxnumber = data[0] ;
int sec_max = MINNUMBER ;
for ( int i = 1 ; i < count ; i++)
{
if ( data[i] > maxnumber )
{
sec_max = maxnumber ;
maxnumber = data[i] ;
}
else
{
if ( data[i] > sec_max )
sec_max = data[i] ;
}
}
return sec_max ;
}

43. 写一个在一个字符串(n)中寻找一个子串(m)第一个位置的函数。

KMP算法效率最好,时间复杂度是O(n+m)。

44. 多重继承的内存分配问题:
  比如有class A : public class B, public class C {}
  那么A的内存结构大致是怎么样的?

这个是compiler-dependent的, 不同的实现其细节可能不同。
如果不考虑有虚函数、虚继承的话就相当简单;否则的话,相当复杂。
可以参考《深入探索C++对象模型》,或者:
http://blog.csdn.net/wfwd/archive/2006/05/30/763797.aspx

45. 如何判断一个单链表是有环的?(注意不能用标志位,最多只能用两个额外指针)

  struct node { char val; node* next;}

  bool check(const node* head) {} //return false : 无环;true: 有环

一种O(n)的办法就是(搞两个指针,一个每次递增一步,一个每次递增两步,如果有环的话两者必然重合,反之亦然):
bool check(const node* head)
{
   if(head==NULL)  return false;
   node *low=head, *fast=head->next;
   while(fast!=NULL && fast->next!=NULL)
   {
       low=low->next;
       fast=fast->next->next;
       if(low==fast) return true;
   }
   return false;
}

来源:http://www.azure.com.cn/article.asp?id=325

一、引言

计算机的出现使得很多原本十分繁琐的工作得以大幅度简化,但是也有一些在人们直观看来很容易的问题却需要拿出一套并不简单的通用解决方案,比如几何问题。作为计算机科学的一个分支,计算几何主要研究解决几何问题的算法。在现代工程和数学领域,计算几何在图形学、机器人技术、超大规模集成电路设计和统计等诸多领域有着十分重要的应用。在本文中,我们将对计算几何常用的基本算法做一个全面的介绍,希望对您了解并应用计算几何的知识解决问题起到帮助。

二、目录

  本文整理的计算几何基本概念和常用算法包括如下内容:

  矢量的概念

  矢量加减法

  矢量叉积

  折线段的拐向判断

  判断点是否在线段上

  判断两线段是否相交

  判断线段和直线是否相交

  判断矩形是否包含点

  判断线段、折线、多边形是否在矩形中

  判断矩形是否在矩形中

  判断圆是否在矩形中

  判断点是否在多边形中

  判断线段是否在多边形内

  判断折线是否在多边形内

  判断多边形是否在多边形内

  判断矩形是否在多边形内

  判断圆是否在多边形内

  判断点是否在圆内

  判断线段、折线、矩形、多边形是否在圆内

  判断圆是否在圆内

  计算点到线段的最近点

  计算点到折线、矩形、多边形的最近点

  计算点到圆的最近距离及交点坐标

  计算两条共线的线段的交点

  计算线段或直线与线段的交点

  求线段或直线与折线、矩形、多边形的交点

  求线段或直线与圆的交点

  凸包的概念

  凸包的求法

三、算法介绍

矢量的概念:

如果一条线段的端点是有次序之分的,我们把这种线段成为有向线段(directed segment)。如果有向线段p1p2的起点p1在坐标原点,我们可以把它称为矢量(vector)p2。

矢量叉积:

计算矢量叉积是与直线和线段相关算法的核心部分。设矢量P = (x1,y1) ,Q = (x2,y2),则矢量叉积定义为由(0,0)、p1、p2和p1+p2所组成的平行四边形的带符号的面积,即:P × Q = x1y2 - x2y1,其结果是一个标量。显然有性质 P × Q = - ( Q × P ) 和 P × ( - Q ) = - ( P × Q )。一般在不加说明的情况下,本文下述算法中所有的点都看作矢量,两点的加减法就是矢量相加减,而点的乘法则看作矢量叉积。

  叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系:

  若 P × Q > 0 , 则P在Q的顺时针方向。
  若 P × Q < 0 , 则P在Q的逆时针方向。
  若 P × Q = 0 , 则P与Q共线,但可能同向也可能反向。

折线段的拐向判断:

  折线段的拐向判断方法可以直接由矢量叉积的性质推出。对于有公共端点的线段p0p1和p1p2,通过计算(p2 - p0) × (p1 - p0)的符号便可以确定折线段的拐向:

  若(p2 - p0) × (p1 - p0) > 0,则p0p1在p1点拐向右侧后得到p1p2。

  若(p2 - p0) × (p1 - p0) < 0,则p0p1在p1点拐向左侧后得到p1p2。

  若(p2 - p0) × (p1 - p0) = 0,则p0、p1、p2三点共线。

  具体情况可参照下图:

from:http://www.programfan.com/article/showarticle.asp?id=2776

  有关微软编程技术的书籍可谓多如牛毛,但读来读去感觉还是MSDN比较权威。这里就拿一个例子来说吧,可能让很多刚开始学习Win32 API程序设计、甚至是一些已经有一定Win32 API经验的人感觉大汗淋漓。

  在学习Win32 API程序设计时,“第一课”我想都会学到“事件循环”吧?很多书给出了类似这样的经典示例:

客户端的处理

客户端并不像服务器端那么复杂,它通常只使用两种消息,即接收数据和终止会话消息,以及需要连接和保持单一连接(服务器端)。另外最主要的就是客户端应用程序必须指定其玩家的位置,以便主机能够检索它们。设置玩家的信息是通过首先将相关数据填入一个DPN_PLAYER_INFO结构体,然后再调用IDirectPlay8Client:: SetClientInfo函数来实现。