1.为什么基类的析构函数是虚函数?
答:编译器总是根据类型来调用类成员函数。但是一个派生类的指针可以安全地转化为一个基类的指针。这样删除一个基类的指针的时候,C++不管这个指针指向一个基类对象还是一个派生类的对象,调用的都是基类的析构函数而不是派生类的。如果你依赖于派生类的析构函数的代码来释放资源,而没有重载析构函数,那么会有资源泄漏。所以建议的方式是将析构函数声明为虚函数。如果你使用MFC,并且以CObject或其派生类为基类,那么MFC已经为你做了这件事情;CObject的析构函数是虚函数。一个函数一旦声明为虚函数,那么不管你是否加上virtual 修饰符,它在所有派生类中都成为虚函数。但是由于理解明确起见,建议的方式还是加上virtual 修饰符。
2.Union和sturct区别(是以选择题形式出现,一个具体的例子)
答:1. struct和union都是由多个不同的数据类型成员组成, 但在任何同一时刻, union中只存放了一个被选中的成员, 而struct的所有成员都存在。在struct中,各成员都占有自己的内存空间,它们是同时存在的。一个struct变量的总长度等于所有成员长度之和。在Union中,所有成员不能同时占用它的内存空间,它们不能同时存在。Union变量的长度等于最长的成员的长度。 2. 对于union的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于struct的不同成员赋值是互不影响的。
3.单链表逆置(c编程)
class Node { public: int value; Node* next; }; Node* ReserveLink(Node* head) { if(head==0 || head->next==0) return head; Node* p, *q, *temp; p= head->next; q=p->next; while(q) { temp = q->next; q->next = p; q = temp; } return p; }
4.1~20的整数的全排列(c编程)
这个题暂时用C#来实现,如果各位有好的办法或者更高效的实现请跟帖讨论
public static string[] PrintArrangementVer1(string inItems) { List list = new List(); if (string.IsNullOrEmpty(inItems)) return null; else if (inItems.Length == 1) { list.Add(inItems.ToString()); } else if (inItems.Length == 2) { list.Add(inItems); list.Add(inItems[1].ToString() + inItems[0].ToString()); } else { for (int i = 0; i < inItems.Length; i++) { string[] strs = PrintArrangementVer1(inItems.Substring(0, i) + inItems.Substring(i + 1, inItems.Length - i - 1)); foreach (string temp in strs) { list.Add(inItems[i].ToString() + temp); } } } return list.ToArray(); }
5.字符串拷贝(特殊要求是源地址和目标地址的空间有重叠的,C编程)
char * strcpy(char * strDest,const char * strSrc) { if ((strDest==NULL)||(strSrc==NULL)) //[1] throw "Invalid argument(s)"; //[2] char * strDestCopy=strDest; //[3] while ((*strDest++=*strSrc++)!=''); //[4] return strDestCopy; } /* 错误的做法: [1] (A)不检查指针的有效性,说明答题者不注重代码的健壮性。 (B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C语言中 类型的隐式转换没有深刻认识。在本例中char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多 的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的 条件表达式。 (C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好处。直接 使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查, 万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错 误,编译器就会检查出来。 [2] (A)return new string("Invalid argument(s)");,说明答题者根本不知道返回值的用途,并且他对内 存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知 情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。 (B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查 返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功 能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可 维护性。 [3] (A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。 [4] (A)循环写成while (*strDest++=*strSrc++);,同[1](B)。 (B)循环写成while (*strSrc!='') *strDest++=*strSrc++;,说明答题者对边界条件的检查不力。循 环体结束后,strDest字符串的末尾没有正确地加上''。 */
答:TCP协议头最少20个字节,包括以下的区域
TCP源端口(Source Port):16位的源端口其中包含初始化通信的端口。源端口和源IP地址的作用是标示报问的返回地址。
TCP目的端口(Destination port):16位的目的端口域定义传输的目的。这个端口指明报文接收计算机上的应用程序地址接口。
TCP序列号(序列码,Sequence Number):32位
TCP应答号(Acknowledgment Number):32位的序列号由接收端计算机使用,重组分段的报文成最初形式。如果设置了ACK控制位,这个值表示一个准备接收的包的序列码。
数据偏移量(HLEN):4位包括TCP头大小,指示何处数据开始。
保留(Reserved):6位值域,这些位必须是0。为了将来定义新的用途所保留。 标志(Code Bits):6位标志域。表示为:紧急标志、有意义的应答标志、推、重置连接标志、同步序列号标志、完成发送数据标志。按照顺序排列是:URG、ACK、PSH、RST、SYN、FIN。
7.sql语句
8.比较次数与初始序列无关的排序方法有哪些?
单链表逆置好像有问题。比较简洁的一个写法:
第四题博主的算法效率太低了!!!