C++基础问题答--续

来源:互联网 发布:幂学集训营怎么样知乎 编辑:程序博客网 时间:2024/06/05 05:13
9.通常的C++程序包括哪几部分?
  C++是面向对象的程序设计语言,所以C++程序和C程序在风格上有很大不同。用户编写的C++程序通常分为.cpp和.h两类,.h文件中通常是类的定义,函数原型或说明以及数据的声明等,然后在.cpp文件中通过包含(#include).h文件来使用。一个C++程序的结构通常是:在程序首部是预处理指令,可以声明需要用到的类库或者包含自定义的函数或类的.h文件,定义常量、宏等等。程序的主函数是main()函数,程序将从这里开始执行。

10.什么是类型转换?
  当类型不同的变量出现在同一表达式中或者赋值符号两边时,会导致类型转换。转换的原则是赋值号右边的值将被转换成赋值号左边变量的类型,然后赋给左边的变量,同一表达式中的不同类型都将转换成与最大类型操作数相同的类型,即从低位字向高位字转换(如int转为float)。有时类型转换会造成数据的丢失。也可以在变量前加(type)来强制使变量转换为需要的类型。比如说某个float类型的变量在输出时需要输出浮点数的信息,而同时它也作为计数值在控制循环次数((int)varname)。

11.何时执行构造函数和析构函数?
  局部对象的构造函数在遇到对象说明语句时执行,并按遇到对象的顺序依次调用,其析构函数则按构造函数的反序进行执行。全局对象的构造函数在main()开始之前执行,并在同一文件中按书写顺序依次执行,但是几个文件之间的全局对象的构造函数执行顺序是不可知的,其析构函数在函数main()结束之后按构造函数反序执行。

12. 如何创建数组?
  数组可以动态创建也可以静态创建。当已知数组大小时,可以简单的定义为intarray[10]。动态创建数组时数组大小可以是已知的,也可以是变元,此时用动态分配符new来创建,定义形式为type*array=new type[size],当然用完数组时必须用delete[]array来释放空间。由于动态创建数组是分配了一块内存空间,因此当数组较大时最好静态分配。对于多维数组,静态分配同前,动态分配则从最高维开始依次用new分配,释放时则从低维到高维依次delete[]。

13.C++会自动检查数组越界吗?
  回答是否定的,也就是说当你的数组越界使用时编译程序不会报错,而只能是在执行时产生非法操作或者得不到正确结果。因此在使用数组时一定要在编程时自己判断是否越界以保证程序的正确性。

14.指针和数组有什么关系?
  指针和数组之间是有密切的关系的。当创建一个数组后,虽然没有定义,但是数组名即是一个指向该数组第一个元素的指针,同样也可以用这个指针对数组进行操作。例如定义数组intarray[10];int*p;p=array;执行后p即指向了数组的第一个元素array[0],最后一个语句相当于p=&array[0](很少这么用)。而任何一个指针变量都可以以数组的方式使用,即通过指针加下标来改变指针的指向。例如定义指针变量int*p;则有p[1]==*(p++)。

15.指针使用中应注意哪些问题?
  指针虽然功能强大,使用灵活,但是很多时候它会导致致命的并且不容易发现的错误。因此使用指针时一定要特别小心,注意不要犯以下错误:首先,未经初始化的指针使用起来是很危险的,因为它可能指向某个未知的内存空间,这样对它操作可能导致严重的后果。解决方法是在使用指针前一定要初始化它的指向(有时null也是不安全的)。其次,对指针的错误理解也可能得不到正确结果甚至产生错误,如数组越界等。另外在使用delete时也容易产生指针错误,delete前一定要确认被释放的指针指向的是有效地址,例如在释放数组时如果忘记了[]将只释放数组的第一个元素所占的空间,而其余元素将被程序"遗忘"在死区,而且很可能当时未被发现,但是如果程序过大或者多次执行将导致资源不足而使系统崩溃。总之由于指针是对内存的直接操作,所以稍不注意就可能产生错误。只有彻底了解指针的使用,并且在编程过程中时刻注意检查指针的指向,指针才会成为有力的工具。

16.向函数传递参数有几种方法?有什么不同?
  向函数传递的参数可以是传值参数,也可以是引用参数,还可能是指针。传值时形式参数即简单的写成typevarname,函数执行后将不改变实参的值。引用传递是把变元的地址传给函数,形式参数写成type&varname,调用时则直接写实参的名字即可,因此函数执行后对实参varname的修改将被保留。指针传递就是把变量的指针传给参数,形参形式为type*varname,显然函数将对指针指向的内存地址直接操作,修改将被保留。

17.什么是类?
  类是面向对象程序设计的基础。一个类定义了一种数据类型,有一点儿像C语言中的结构类型(struct)。从计算机科学的观点来说,一种数据类型应该包括一系列的状态和一系列的操作,操作引起状态的转化。

18.什么是对象?
  在声明一个整型变量时,我们会说:"inti;",这时我们的意思是,"i是整数类型的一个对象"。在面向对象的C++程序设计中,对象意味着类的实例。

19.什么是友元?
  友元是C++为某个类提供的允许其它类或者函数访问它的机制。友元可以是函数,也可以是类。一个类可以给予它的友元存取和访问自己的特权。

20.友元违反数据封装原则吗?
  恰当地应用友元,不但不会破坏封装性,反而会加强它。
  在编程的时候,我们经常遇到这样的情况,就是两个类之间有着紧密的联系,它们常常需要互相访问对方的数据和成员函数。实现这种编码的最好方法,就是将这两个类互相设置成友元。
  这样做的好处是,我们可以使两个类中的私有成员保持它的私有性。有些初级编程者为了避免使用友元,常常将数据设置成public的,或者利用public的get()和set()对私有成员进行存取,这样做实际上反而破坏了数据的封装性。采用get()和set()这种存取函数的机制,与直接设置公有数据取得的效果,几乎一样差。它们只是将私有数据成员的名字隐藏了起来,而私有数据成员其他的一切,都暴露出来。
  同样,将一些函数设置成友元也不会影响类的封装特性。友元函数和类的成员函数一起,构成了类的封装边界。换句话说,友元函数对于封装带来的影响,就如同成员函数的影响一样。谁会说成员函数影响了类的封装性呢?

21.构造函数是用来做什么的?
  "构造函数从尘土中建造大楼"。构造函数完成对象的初始化工作,它们将一堆毫无意义的比特转化成一个个活生生的对象。它们为对象初始化各种数据,并分配各种资源,包括内存、文件、socket等等。

22.假设List是一个类的名字,那么"List x"和"Listx()"之间有区别吗?
  区别大了!
  举例说明:函数f()声明了一个List类的局部对象x:
  void f()
  {
   List x; // 局部对象x
   // ...
  }
  但是,函数g()在内部声明了一个函数x,它返回List的一个对象
  void g()
  {
   List x(); //局部函数,函数名x
   // ...
  }

23.析构函数通常做什么工作?
  析构函数用来释放对象所占有的所有资源,包括内存、文件、socket连接等等。它的工作一般和构造函数的初始化工作相对。最常见的例子就是构造函数用new,而析构函数用delete。

24.编写析构函数时,需要显式调用成员对象的析构函数吗?
  不需要。
  类的析构函数自动调用成员对象的析构函数。

25.编写派生类的析构函数时,需要显式调用基类的析构函数吗?
  不需要。
  派生类的析构函数自动调用基类的析构函数。

26.结构和类有什么区别?
  C++扩展了C中的结构,使结构也可以定义类。唯一的区别是,class定义的类中的缺省访问级别是private,而struct定义中缺省级别为public。

27.联合与类有什么区别?
  联合也可以用来定义类,与结构类似其缺省访问级别是public。如果要求创建的对象的元素共享同一内存地址时就用union来定义该类。但是使用联合定义类时有以下限制:联合不能继承其他的类,也不能被继承,不能含有虚成员函数,不能有静态成员变量,不能有重载运算符"="的对象作成员,不能有含有构造函数和析构函数的对象作成员。

28.哪些运算符可以被重载?哪些不能?
  大部分运算符都可以被重载,不能被重载的运算符有 "。" , "?:", "::" 和 "*"。 

29.如何进行文件操作?
  要处理文件I/O,程序首部必须包含头文件fstream.h。其中定义了ifstream,ofstream,fstream等类,它们分别从istream和ostream派生而来,而istream和ostream是从ios派生而来,所以ifstream,ofstream,fstream可以存取ios定义的所有运算。需要注意进行文件操作(打开、读写)时都需要检测操作是否成功以保证程序正确进行处理。

30.如何打开和关闭一个文件?
  通过把文件和流联系起来打开文件。打开文件之前要先获得一个流(输入流ifstream,输出流ofstream或者输入输出流fstream)。然后使用函数open()把流和文件联系起来打开文件,其原型为voidopen(char *filename,int mode,intaccess);其中filename为文件名,mode值为文件打开方式,access值为存取文件方式。实际上常常不调用函数open()而直接用ifstream或ofstream的构造函数来打开文件。要关闭一个文件,就用该文件关联的流调用成员函数close()即可。

31.如何读写一个文件?
  读写文本文件时只需将与文件相关联的流与运算符<<、>>连用即可。但是这样读写文本时将发生某些字符转换,为避免这种情况,可采用C++的二进制I/O函数put(),get(),read()和write()。它们的原型即说明如下:
  istream &get(char&ch);//从流中读入一个字符存入ch中,返回对流的引用。
  ostream &put(char ch); //将ch写入流,返回对流的引用。
  istream &read(unsigned char *buffer,intnum);
  //从相关流中读入num个字节存入buffer所指的缓冲区中,返回对流的引用。
  ostream &write(const unsigned char *buffer,intnum);
  //把buffer所指的缓冲区中的num个字节写入相关的流中,返回对流的引用。

32. 如何判断文件结束?
  成员函数eof()可以跟踪何时到达文件尾,当到达文件尾时eof()返回值不为0,否则为0。
原创粉丝点击