这是我自nsfocus面试以来,第一次参见面试,感谢adk给我这个机会,为了保密,这里用adk代表我面试的这家公司。    中午一觉睡醒,收到了adk工作人员的电话,让我晚上8:30到卓刀泉大厦面试。我很高兴他在我睡完午觉之后才给我电话,不然我这午觉估计要失眠了,^_^。    adk是我等待已久的公司,所以准备也要充分点了。我找marilyn借了notepad,把标记机软件上层装上,因为这是与他们公司岗位最接近的一个项目,我还把cactus留在我这里的样标全部拿上,到时候给他们一点印象也是好的,^_^。    7点多,我就到了酒店,足足早到了一个多小时,看了还是面试经验不够,卡时间没有经验。我跑上12楼,发现一个人都没有,以为走错地方了,打个电话叫cactus帮忙确认了一下,这才安心的跑到楼下大厅里面去等。到了7:50,匆匆跑进来一个女生,一看我就知道碰到同路人,轻松聊了几句,上去之前她居然先说了good luck,呵呵,看来我应该再绅士一点,^_^。    8:20,我把marilyn手提打开,把软件准备好,想着马上要进去了,节省点开机时间。但很不幸,到了8:30,那房间还是一点反应都没有,这个时候有位在隔壁房间面试的仁兄,直接跑过去敲门了,里面出来一个面试官,我趁机上去询问一下我们那房间是不是有人面试(因为我从来没有看到里面有人出来过),那位面试官要我再等等,最好不要敲门,以免打扰人家,^_^,幸亏没有直接上去敲门。    等到8:50,我先把手提关了,我怕电池撑不住。这时隔壁房间被面的一个男生出来了,小聊了几句,他是计算机的(adk是软件公司,估计来面试的大多数都会是计算机的),他很郁闷的样子,说那些面技术的都超级变态,c++把他问得一句话都没的说,我问他问哪些问题,他说简历上写了什么,就问什么,比如windows编程、c++等等,他说他对这两项写了精通,^_^,我知道问题的症结了。    那人一走,我就过去敲门了,门开了,里面传来女生爽朗的笑声,晕啊,这些人难道海聊上了?害我等了这么久,出来的面试官叫我再等一会儿,还没完,虽然有点失望,但总归看到希望了,那就再等等吧……    大概9:10,我进去了,面试官是两位男同胞,一个干瘦,一个微胖,一个颧骨突出(就像我这样),一个圆头圆脑。他们先看简历,看到项目经历,来了一句,你项目还蛮多的啊(我心中窃喜,^_^),我知道他们肯定会把落脚点放在“标记机软件上层”项目上,因为我已经把土土的“标记机软件上层”改名为“振镜标记机二维CAD软件系统”,而且把CAD狠狠的加粗了,adk不看这个还看啥呢?我还告诉他们我已经把这个软件带过来了,如果有时间,想请他们指点指点。    他们先让我把CAD软件系统的类图绘制出来,我稀里哗啦把DocContainer、State、Command画上了,然后他们要我介绍这些类之间的协作关系。接着要我解释一下MFC中如何实现splitter窗口,我老实交代,对这块知之甚少,我只能说个大概,也许是先将一个framewnd分成两个子framewnd,然后再在子framewnd里面包容view什么的……不敢咬定一定正确,但我希望自己的回答能够体现自己对frame->view->doc的理解。他们对这个情况表示理解,紧接着他们问了一个文件依赖关系的问题,大概情况就是,有三个类:A、B和C,他们的定义大概如下:        A.h:    #include "C.h"    class A    {         C *m_pC;    }    B.h:    #include "A.h"    class A    {         A m_A;    }        他问我如何减少上述代码中的文件依赖关系,并说明原因。我说可以把A.h中的#include "C.h"替换成class C;因为A.h只需知道C的定义即可,不需要知道C的实现,而B.h定义一个实例,编译的时候势必要去找到A的构造函数的入口,因此必须保留A的实现。他对这样的回答貌似比较认可。    接下来要我写strcpy,这个好经典,一下子写完了,他们比较认可,但我稀里糊涂的把函数头写错了,应该是:        char* strcpy(char *des, const char *src);    {        if(des == NULL || src == NULL) return NULL;        while((*des++ = *src++) != �);    }        我把const写漏了,不过他们一提醒,我马上改过来了。其实犯错误不要紧,关键是要体现你对知识的掌握程度和你的思维能力,我改过来以后他们还是非常认可的,但我知道我写的里面还是有个漏洞,那就是没有判断des == src的情况,这种情况应该直接返回des,以免不必要的开销,不过这一点他们没有提。    接下来要我写memcpy,我的答案是:        void memcpy(void *des, void *src, size_t len);    {        if(des == NULL || src == NULL) return NULL;        while(len– > 0)        {            *((char*)des) = *((char*)src); des++; src++;        }    }            他让我考虑异常情况,我想到了覆盖,一种情况是des + len > src && des < src的情况,这种情况上面代码应该是可以搞定的,但我当时有点蒙,想错了,觉得似乎有问题,他看我有点困难,就直接告诉我这种情况不存在问题,他让我考虑另一种情况,也就是src + len > des && src < des的情况,这样显然是存在问题的,我一看,迅速反应过来,这种情况应该反过来拷贝,他对我反应速度比较满意,然后就让我写代码了:        void memcpy(void *des, void *src, size_t len);    {        if(des == NULL || src == NULL || des == src) return NULL; &nbsp ;      if(des + len > src && des < src)        {            des += len; src += len;            while(len– > 0)            {                *((char*)des) = *((char*)src); des–; src–;            }        }        else        {            while(len– > 0)            {                *((char*)des) = *((char*)src); des++; src++;            }        }    }           我问他这代码怎么样,他说能回答到这一步已经很不错了。       再接下来,他又出了个问题,要我用排列的方式打印出1-9九位数,各个数字只能出现一次,不能重复。我问他,是不是要考虑时间复杂度,他说先按自己的思路写个程序再说,我第一反应就是一个9重for循环,这是初中老师交的,^_^,第1个数有9种可选方案,第2个数有8种可选方案……依次类推,就是9重循环。他就提问了,说这9重循环一点扩展性都没有,让我想想办法,他提到9重和8重有什么区别,我一下子就想到了递归,他很满意的说,那你写个递归看看,我写了一段伪码:        void display(int a[], int size)    {            if(size > 0)              {            for(i = 1; i < N - m; i++)            {                在数字数组中找到一个没被用到的数字;                display(a[], size - 1);            }        }        else        {            printf 数字数组;        }    }           调用者这样写:        main    {        int a[N];        for(i = 1; i < N; i++)        {            将a数组所有元素清为 N + 1            a[0] = i;            display(a, N - 1);        }    }        他叫我分析这个算法的复杂度,我想了20秒,写了个O(m!),他说不对,按我这种算法,他觉得应该是O(m * m!),他问我m来自于哪里,我用了2秒钟时间告诉他,这个m应该花在“在数字数组中找到一个没被用到的数字”上。他然后就似乎比较满意了。其实面试官要搞死你很简单(我就还没碰到过搞不死的本科生,^_^),关键是体现自己对知识的掌握程度和思维能力(网上很多人都是这么说的,^_^)    问完了算法,估计他们觉得再问也没什么意思了,就回到c++上面,就着我做的卷子问问题。他先问了一个sizeof的问题,大概就是:        class A    {        A();        virtual ~A();    }    class B : public A    {        char buf;    }        他问我sizeof(B) == ? 我画了个内存映像图,然后告诉他是8,他比较认可这答案,我刚刚在vc里面测试了一下,的确是对的。他注意到我画了个虚函数表,就问我虚函数表是一个类共用还是每个对象都有一个,我答是一个类共有。不过这里还是有个未果的问题,那就是c++如何实现dynamic_cast,利用的是什么信息,我答到用的是虚函数表,虚函数表中有一个指针指向基类的虚函数表,这个好像答错了,还得好好钻研一下。    最后两个问题是设计模式的,问我strategy模式和template method模式的区别,我说了一堆,可惜最后没有坚持,因为我对template method不是很熟悉,其实我说的应该是对的,结果却自己把自己否定了,唉…..败笔!    另一个设计模式问题,他让我画出我们系统用到的composition模式和command模式综合运用的例子,我画了一个cut = copy + delete的例子,总算挽回一点面子,^_^    到这时,应该已经面了一个小时了,估计他们觉得时间不够了,最后叫我随便说几句英语,介绍一下我做过的项目和跟组员交流的体会,我大概说了5分钟,中间没有忘记把样标拿出来给他们展示,并且用english跟他们介绍,他们非常感兴趣的样子,^_^。    最后让我问了2个问题,我表示很可惜没有把软件演示给他们看,他们说,不用看软件了,看我画出来的UML图和打出的样标,就已经很好了,最后一句话是:“我们对你做的东西很感兴趣”,希望这不是一句安慰我的话。