看流星社区

 找回密码
 注册账号
查看: 2716|回复: 0

C++常见问题解答

[复制链接]

该用户从未签到

发表于 2011-3-26 10:18:42 | 显示全部楼层 |阅读模式
这篇文章对新手帮助很大,能解决一些常见的问题,希望可以帮到新手们!!

引言篇
1.学习C++是否必须先了解C?

2.怎样开始学习C++?

3.改进C++程序的最好方法是什么?

4.对于小的程序C优于C++,对吗?

5.C是C++的子集吗?

6.C++与C有什么区别?

7.为什么用C++产生的"Hello World"的程序代码要比用C产生的长十倍?

8.什么是面向对象的程序设计(OOP)?


1.学习C++是否必须先了解C? 
 不是,C++与C的公共部分比C还容易学习,由于C++比C的类型检查更严格更富于表现力,因此产生的错误就更少,又由于C++能使你毫不困难地描述更多的事物,因此所需的诀窍就更少,而且可利用的库也要比C多.所要学习的C++子集并不是C的全部.

2.怎样开始学习C++? 

  很显然,这非常依赖于你已经掌握的知识和你学习C++的动机.如果你是个编程新手,我强烈建议你找一位有经验的程序员来帮助你.否则概念性的错误以及程序实际执行过程中所发生的问题将使你的学习大受挫折.
  你需要一本C++学习教程.该教程起到在线帮助文档的作用. 其原因是带有足够多代码的编程语言和库文档对概念的解释不见得就很清楚。
  当选择一本书时,要选将标准C++和标准库结合在一块描述的书.如,象字符串的输入应这样;
  string s;// 标准C++风格
  cin>>s;
  而不要象这样:
  char s[MAX]; /* 标准C风格 */
  scanf("%s",s);
  多看看有丰富编程经验的程序员推荐的书,记住,对任何人来说没有哪一本是最好的,看看ACCU(C和C++用户协会)站点上的书评.
  为了写出合乎习惯的C++语句,应避免简单地用你以前学过的语言的风格写C++代码,仅仅通过改变句子排列顺序是得不到什么进步的.看看《Learning Standard C++ as a New Language》一书中关于如何学习C++的讨论内容.

3.改进C++程序的最好方法是什么?
  这我没法说,主要取决于你如何用它,有很多人都轻视抽象类和模板.相反他们过多地使用casts和宏.

4.对于小的程序C优于C++,对吗?
  我没有这样的观点,我还未见过在不缺好的C++编译器的情况下,有优于C++的C小程序

5.C是C++的子集吗?
  从严格的数学意义上讲,C不是C++的一个子集.有些程序是有效的C程序却不是有效的C++程序,甚至在一些代码的编写方面,C与C++也有不同的意思.不过C++支持C所支持的每一种编程技术.每个C程序从本质上来讲也都可以相同的方式用C++来编写,并且有着相同的时间和空间效率.在几小时内将几万行符合ANSI标准的C程序转换成C++风格的C++程序是常见的.因此C++是ANSI C的超集就像ANSI C是K&R C的超集而ISO C++又是C++的超集一样.
  一般的C程序都符合C++语法,比如Kernighan和Ritchie合著的《The C Programming Language》(第二版)中的任何一个例子也都是C++程序.
有关C/C++兼容的问题例子:
  int main()
  {
   double sq2=sqrt(2); /* 不是C++程序:调用了一个未声明的函数 */
   int s=sizeof('a'); /* 在C中用 sizeof(int) . */
  }
  调用一个未声明的函数是C中不好的风格而在C++中则是不合法的.
  void f();
  void g()
  {
   f(2);
  }
  在C语言中 void类型的指针能被转换为任意类型的指针,分配内存的典型做法是调用函数malloc().....
  void * malloc(size_t);
  void f(int n)
  {
   int *p=malloc(n*sizeof(char)); /*非C++用法,C++是用new分配内存的*/
   char c;
   void* pv=&c;
   int *pi=pv; /*隐含有将void类型指针转换为int类型的指针,在C++中不用*/
  }
  注意隐含地将void类型指针转换为int类型的指针会引起潜在的alignment错误.
  从C转换到C++时,需注意C++的关键字要比C来的多
  int class =2; /* 在C中是正确的, 在C++中则有语法错误*/
  int virtual=3; /* 在C中是正确的, 在C++中则有语法错误*/
  除了一些象上面所举的例子外(《The C++ Programming Language》(第三版)的附录B中详细列出了标准
  C++与C的这类区别)C++是C的一个超集(附录B可以从网上下载)

6. C++与C有什么区别?
  C++是C的直接后裔,几乎将C当作一个子集而差不多保留了C的全部内容,C++提供了更强的类型检查机制并直接支持范围更广的编程风格.在这种意义上说C++是"更好的C",它支持C语言的编程风格并有更好的类型检查(又不失其原有的高效率).类似的,ANSI C 是比K&R C更好的C,另外C++支持数据抽象,面向对象的编程和类编程(请见《The C++ Programming Language》(第3版),可以从网上下载的附录B中讨论了兼容性问题.)
  我还未曾见过哪一个程序用C表达比用C++来得更好(我认为不存在这样一个C程序,其结构与C++完全等价)
  然而,在某些情况下由于C++得不到充分的支持,而使用C更有利.
  要理解有关C++的设计以及C++与C的关系的一些讨论,请见《The Design and Evolution of C++》;  

7.为什么用C++产生的“Hello World”的程序代码要比用C产生的长十倍?
  在我的机器上不会有这种现象,在你的机器上也不会有.实际上,在我的机器“hello world”程序的C++版本的目标代码比C要小.没有语言方面的原因使得一种版本的程序代码比另一种的要长.只有一种情况,那就是实现一种语言的人是如何组织标准库的.如果一种版本要比另一版本大得多,则要向大的一方的实现者提出所发现的问题.

8.什么是面向对象的程序设计(OOP)?
  面向对象的设计方法是一种进行程序设计的新方法,它吸取了结构化程序设计的先进思想,为解决程序结构过于复杂而产生。它的思想是在进行程序设计时,把整个问题分成由相关部分组成的组,每个组考虑和组相关的代码和数据,同时这些分组将按层次关系组织起来,每个分组转换为对象的独立单元。面向对象的程序设计语言都具有多态性、继承性、封装性等特点。

基础篇
9.通常的C++程序包括哪几部分?
10.什么是类型转换?
11.何时执行构造函数和析构函数?
12.如何创建数组?
13.C++会自动检查数组越界吗?
14.指针和数组有什么关系?
15.指针使用中应注意哪些问题?
16.向函数传递参数有几种方法?有什么不同?  
17.什么是类?
18.什么是对象?
19.什么是友元?
20.友元违反数据封装原则吗?
21.构造函数是用来做什么的?
22.假设List是一个类的名字,那么"List x"和"List x()"之间有区别吗?
23.析构函数通常做什么工作?
24.编写析构函数时,需要显式调用成员对象的析构函数吗?
25.编写派生类的析构函数时,需要显式调用基类的析构函数吗?
26.结构和类有什么区别?
27.联合与类有什么区别?
28.哪些运算符可以被重载?哪些不能?
29.如何进行文件操作?
30.如何打开和关闭一个文件?
31.如何读写一个文件?
32.如何判断文件结束?
-----------------------------------------------------------------------------------------------------------------

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

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

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

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

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

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

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

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

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

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

22.假设List是一个类的名字,那么"List x"和"List x()"之间有区别吗?
  区别大了!
  举例说明:函数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()把流和文件联系起来打开文件,其原型为void open(char *filename,int mode,int access);其中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,int num);
  //从相关流中读入num个字节存入buffer所指的缓冲区中,返回对流的引用。
  ostream &write(const unsigned char *buffer,int num);
  //把buffer所指的缓冲区中的num个字节写入相关的流中,返回对流的引用。

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

提高篇  
33.new和delete比 malloc和free有哪些优点?
34.C++ 中可以使用printf()和scanf()吗?
35.C++中的输出cout<<能够指定输出数据的域宽和精度吗?
36.如何向函数传递数组?
37.我如何才能防止其他的程序员看到我的类的私有成员从而维护数据封装性呢?
38.封装是一种安全机制吗?
39.可以向构造函数传递变元吗?
40.如何向函数传递对象?
41.为什么友元关系不具有传递性,也不能通过继承得到?
42.如何在一个构造函数的内部调用另一个构造函数?
43.对于类C来说,缺省构造函数一定是C::C()的形式吗?
44.为什么含有静态成员的类产生链接错误?
45.局部对象的析构顺序是怎样的?
46.能够重载类的析构函数吗?
47.如果我的对象是通过new创建的,那么我可以显式地调用析构函数清除这个对象吗?
48.说明指针变量和引用变量时,*或&应该与类型名连在一起还是变量名连在一起?
49.如何进行运算符重载?
50.在函数定义中使用const修饰符有何作用?
51.派生类可以继承基类的哪些部分?
52.public,protected,private有什么区别?
53.什么要使用模板?
54.C++中可以嵌入汇编吗?

----------------------------------------------------------------------------------------------------------
33.new和delete比 malloc和free有哪些优点?
  new和delete完成与malloc和free相似的功能,但是它们相比之下有以下优点:
  i. 用new自动分配空间时容量是自动计算的,不必使用sizeof运算符,所以能够分配到足够的空间以容纳指定类型的对象,避免发生错误。
  ii. 用new分配内存后将自动返回指定对象类型的指针,而用malloc则需显式的使用强制类型转换。
  iii. new和delete都可以重载,而malloc和free不存在此功能。

34. C++中可以使用printf()和scanf()吗?
  可以,因为C++是兼容C的功能的。但是C++中有自己的输入输出符号:<<和>>。例如语句 cout<<"Hello" <<" world!\n"将在屏幕上输出Hello world!并换行。cout,cin与<<和>>连用可以处理C++的任何内部数据类型。与printf和scanf相比它们具有如下优点:安全,编译器会静态地事先得知变量类型而不是由%动态获得;简单快速,不易出错;而通过重载运算符<<和>>,可以对用户定义的对象直接进行输入输出操作,这是printf和scanf所不能及的。

35.C++中的输出cout<<能够指定输出数据的域宽和精度吗?
  可以通过设置格式标志来完成,另外流类ios还有三个成员函数来设置格式参数。它们分别是:
  int width(int w);//设置域宽,w为新域宽,返回以前的域宽。
  int precision(int p);//设置精度,p为设置的精度,返回原来的精度值。
  char fill(char ch);//设置填充字符,ch为新的填充字符,返回原来的值。
  它们都可以由cout调用。

36.如何向函数传递数组?
  对于传递的一维数组,形式参数可以写成指针、有界数组、无界数组三种方式,例如void fun(int *x)或者void fun(int x[10])或者void fun(int x[])。这三种方法效果相同,在调用时实参均应该是指向数组的指针。传递多维数组时,除第一维外其余各维大小必须指定,如void fun(int x[][2][6])。

37. 我如何才能防止其他的程序员看到我的类的私有成员从而维护数据封装性呢?
  这个问题本身就存在问题。封装针对的是编码,而不是程序员。
  其他程序员看到你编写的类的私有成员,并不意味着这个类的封装性被破坏了,只要这些程序员不依赖于他们所看到的私有成员编写他们的程序,那么你的类的封装性就没有受到任何影响。"私有"这个词是针对类而言的,不是针对你和其他程序员。

38.封装是一种安全机制吗?
  不是。
  封装并不等于安全。封装是用来防止错误发生的,封装不能用来防间谍。

39.可以向构造函数传递变元吗?
  可以。通过向构造函数传递变元,可以对对象进行特定的初始化。

40.如何向函数传递对象?
  传递对象参数可以和传递其他类型的参数使用相同的方法。对象可以通过传值方式传递给函数,也就是传递给了函数一个拷贝。由于是相当于创建了一个新对象,那么它的构造函数和析构函数是否要执行呢?结果是这样的:新对象没有执行构造函数,但是函数结束时执行了析构函数。原因是新对象应该保持原对象的状态,因此不能执行构造函数重新初始化,而是执行拷贝构造函数,而最后这个拷贝还是要被撤销的,所以要执行析构函数。当然,如果希望对象能够被函数改变也可以向函数传递对象的引用或者指针。

41. 为什么友元关系不具有传递性,也不能通过继承得到?
  很明显,这么做是合情合理的。拿生活中的朋友关系类比:我宣称你是我的朋友,但这并不代表我也认为你的儿女或者你的朋友也是我的朋友。
  对于你朋友的儿女,你不一定信任,这说明朋友关系不能继承。如果class C声明class Base是一个友元类,并且class Derived是class Base的派生类,class Derived并不能自动的成为class C的友元。
  对于你朋友的朋友,你不一定信任,这说明朋友关系不能传递。如果class Bob声明class John是一个友元类,并且class John声明class Salla是一个友元类,class Salla并不能自动的成为class Bob的友元类。

42. 如何在一个构造函数的内部调用另一个构造函数?
  这是不可能办到的。如果你调用了另一个构造函数,编译器将创建一个临时局部对象,而对于当前的对象起不到任何初始化作用。如果想要两个构造函数共享代码,可以创建一个私有成员函数initial(),在两个构造函数中分别调用它即可。

43. 对于类C来说,缺省构造函数一定是C::C()的形式吗?
  不是这样的。
  缺省构造函数是这样一类构造函数:调用它时可以不给出任何参数。所以不带任何参数的构造函数当然是缺省构造函数,比如:
  class C
  {
   C(); //缺省构造函数
  };
  但是,缺省构造函数也可以带有参数,只要这些参数都具有缺省值即可,比如:
  class C
  {
   C(int a=0, int b=0); //缺省构造函数
  };

44.为什么含有静态成员的类产生链接错误?
  产生这种错误的原因通常是编程者没有满足这样一条原则:类的静态数据成员必须被显式的定义,并且只能在一个编译模块中定义一次。如果你违反这一原则,就会得?quot;undefined external" linker error。举例说明:
  // Fred.h
  class Fred {
   public:
   // ...
  private:
   static int j_; // 声明静态数据成员 Fred::j
   // ...
  };
  你必须在某个文件中定义Fred::j,否则链接不能通过,比如在Fred.cpp文件中定义它:
  // Fred.cpp
  #include "Fred.h"
  int Fred::j_ = 0;

45.局部对象的析构顺序是怎样的?
  局部对象按照它们建立顺序的反顺序进行析构。最早创建的对象最晚被析构。
  在下面的例子中,b的析构函数首先被调用,然后是a的析构函数。
  void f()
  {
   C a;
   C b;
   //……
  }

46. 能够重载类的析构函数吗?
  不能。
  对于一个类来讲,只能有一个析构函数,也一定是class_name::~class_name()的形式。析构函数没有任何参数,也没有返回值。我们不能传递给析构函数什么参数,因为我们不能显式的调用析构函数。

47. 如果我的对象是通过new创建的,那么我可以显式的调用析构函数清除这个对象吗?
  不能。
  你必须通过delete来清除这个对象。delete操作自动调用相应的析构函数,但是它比析构函数多做了一件重要的事情,它释放了对象本身占有的内存。需要铭记在心的是:delete做了两件事情,它调用了析构函数,并且释放了对象占用的内存。

48.说明指针变量和引用变量时,*或&应该与类型名连在一起还是变量名连在一起?
  当定义单个变量时这两种做法是一样的,只是反映了不同的风格而已,可以认为与类型名连在一起时得到一种指针类型。但是实际上并非如此,当多个变量同时定义时也许会出现问题,如int* a,b;将会定义一个指针类型变量a和一个整型变量b。因此只要清楚真正的含义,在实际应用时可以灵活一些而不会出错。

49. 如何进行操作符重载?
  操作符重载是十分有用的,特别是在面向对象的程序设计中,可以对自定义的对象直接用操作符连接,增强了直观性,例如重载加号+使它完成两个复数(用户定义的类)的加法。进行操作符重载时需要用到关键字operator,为某个类的对象重载操作符的成员函数定义形式为:returntype operator#(para-list);其中returntype是操作后返回的数据类型,通常是参与计算的对象的类型,#代表被重载的操作符,当# 是单目操作符时参数表为空,当#为双目操作符时参数表中将是右操作数。也就是说是操作符左边的对象调用的函数。也可以用friend来重载关于类的运算符,这时函数将不是类的成员(没有this指针)。这样重载函数将显式的传递操作数,所以重载单目操作符将有一个参数,而重载双目操作符将有两个参数。但是不能用friend重载=,(),->运算符,而且参数需要是引用类型。

50. 在函数定义中使用const修饰符有何作用?
  关键字const可以说明常量,但是在函数定义中有更大的作用。当函数的参数是指针或者引用变量时(非传值参数),如果前面加修饰符const,则可以避免被指向或被引用的变量。当成员函数被const修饰时,例如void fun() const;则表示该函数不会对调用它的对象产生影响。

51. 派生类可以继承基类的哪些部分?
  基类中的所有声明为public和protected的成员,派生类都可以继承,但是声明为private的部分,派生类则无权继承,这是为了将来基类中的(私有)成员一旦修改不会影响到其派生类。

52. public,protected,private有什么区别?
  它们都是类成员的访问级别,public标注的成员具有公有级别,也就是其他函数或者类的对象都可以访问它;private表示私有成员,它们不能被本类以外的对象或者函数引用;protected修饰的成员是保护成员,除了本类或本类的派生类可以存取外其他都无权访问。

53. 为什么要使用模板?
  有些操作对不同数据类型的数据操作相同,但是不得不对各个数据类型分别编写代码。为了让程序更加简洁通用,用template关键字将不同类型数据的共同操作定义成模板,以后某个类型的数据需要进行这个操作时就可以只指定数据类型以后直接调用该模板。可以编写模板函数,也可以编写模板类(可以根据不同的数据类型生成不同的对象),定义时只需在前面加上template <class T>,T表示程序中待定的数据类型。模板函数在调用时无需显式指定数据类型,直接调用即可;模板类调用时需在程序中需要指定数据类型的尖括号内给出具体的数据类型(如int)。

54. C++中可以嵌入汇编吗?
  可以的,通过关键字asm可以将汇编语言直接嵌到C++程序中。语法为:
  asm("string")或者asm instru或者asm{instru sequence},其中string,instru,instru sequence都是传给汇编程序的汇编语句。如果对汇编语言很精通,有时候在C++程序中嵌入汇编代码将会大大提高程序的效率。



类型                            运算符                       例子
全局变量或全局函数                   : :                              (全局)        : : GetSystemDirectory
类中的域变量或函数                   : :                              (类域)        CWnd::FromHandle  
括号及函数调用                   ( )                           (a+b)*(a-b)
指针指向的结构或类种的域变量        - >                           (CWnd *wnd)-> FromHandle
结构或类中的域变量                   .                            (CWnd wnd). FromHandle
数组下标运算符                  []                          nYearsMonthsDays[10][12][366]
内存分配运算符                 new                          new CWnd
内存释放运算符                delete                          delete (CWnd *wnd)



1. 保留字
  C++中,保留字也称关键字,它是预先定义好的标识符。见关键字的解释。

2.关键字
  C++中已经被系统定义为特殊含义的一类标识符。C++中的关键字有:

auto        double        int        struct         break         else
long        switch        case        enum        register        typedef
char        extern        return        union        const        float
short        unsigned        continue        for        signed        void
default        goto        sizeof        volatile        do        if
static        while        asm        _cs        _ds        _es
_ss        cdecl        far        huge        interrupt        near
pascal        class        public        private        catch        protected
delete        new        template        friend        this        inline
throw        try        operator        virtual        overload(现不用)


3.标识符
  对变量、函数、标号和其它各种用户自定义对象的命名。在C++中,标识符长度没有限制,第一个字符必须是字母或下划线,其后若有字符则必须为字母、数字或下划线。例如count2,_x是正确的标识符形式,而hello!,3th则是错误的。在C++中标识符区分大小写,另外标识符不能和C++中的关键字相同,也不能和函数同名。

4.声明
  将一个标识符引入一个作用域,此标识符必须指明类型,如果同时指定了它所代表的实体,则声明也是定义。

5.定义
  给所声明的标识符指定所代表的实体。

6.变量
  某个作用域范围内的命名对象。

7.常量
  常量是不接受程序修改的固定值,可以是任意数据类型。可以用后缀准确的描述所期望的常量类型,如浮点类型常量在数字后加F,无符号整型常量加后缀U等等。此外还有串常量如"Please input year:",反斜线字符常量如\n表示回车符。

8. const说明符
  const是在变量声明或函数声明时所用到的一个修饰符,用它所修饰的实体具有只读属性。

9. 输入
  当程序需要执行键盘输入时,可以使用抽取操作付">>"从cin输入流中抽取字符。如:
  int myAge;
  cin >> myAge;

10.输出
  当程序需要在屏幕上显示输出时,可以使用插入操作符"<<"向cout 输出流中插入字符。如:
  cout << "This is a program. \n ";

11.流
  流是既产生信息又消费信息的逻辑设备,通过C++系统和物理设备关联。C++的I/O系统是通过流操作的。有两种类型的流:文本流,二进制流。

12.标准输入输出库
  它是C++标准库的组成部分,为C++语言提供了输入输出的能力。

13.内置数据类型
  由C++直接提供的类型,包括int、float、double、char 、bool、指针、数组和引用。

14.字符类型
  包括 char、signed char、unsigned char三种类型。

15.整数类型
  包括 short、 int、long 三种类型。

16.long
  只能修饰 int , double.
  long int 指一种整数类型,它的长度大于等于int型.
  long double 指长双精度类型,长度大于等于double型。  

17.short
  一种长度少于或等于int型的整数类型。

18.signed
  由它所修饰的类型是带符号的. 只能修饰 int 和 char .

19.布尔型
  一种数据类型,其值可为:true, false 两种。

20.浮点类型
  包括float, double , long double 三种类型。其典型特征表现为有尾数或指数。

21.双精度类型
  浮点类型中的一种。在基本数据类型中它是精度最高,表示范围最大的一种数据类型。

22.void类型
  关键字之一,指示没有返回信息。

23.结构类型
  类的一种,其成员默认为public型。大多用作无成员函数的数据结构。

24.枚举类型
  一种用户自定义类型,由用户定义的值的集合组成。

25.类型转换
  一种数据类型转换为另一种,包括显式,隐式两种方式。

26.指针
  一个保存地址或0的对象。  

27. 函数指针
  每个函数都有地址,指向函数地址的指针称为函数指针,函数指针指向代码区中的某个函数,通过函数指针可以调用相应的函数。其定义形式为:
  int ( * func ) ( char a, char b);

28.引用
  为一个对象或函数提供的另一个名字。

29.链表
  一种数据结构,由一个个有序的结点组成,每个结点都是相同类型的结构,每个结点都有一个指针成员指向下一个结点。

30.数组
  数组是一个由若干同类型变量组成的集合。

31.字符串
  标准库中的一种数据类型,一些常用操作符如+=,==支持其操作。

32.运算符
  内置的操作常用符号,例如+,* ,& 等。

33.单目运算符
  只能对一个操作数进行操作

34.双目运算符
  可对两个操作数进行操作

35.三目运算符
  可对三个操作数进行操作  

36.算术运算符
  执行算术操作的运算符,包括:+,-,*,/,%。

37.条件运算符
  即"?: " 。
  其语法为:
  (条件表达式)?(条件为真时的表达式):(条件为假时的表达式)
  如:x = a < b ? a : b;
  相当于:
  if ( a < b)  
  x = a;
  else
  x = b;  

38.赋值运算符
  即:" = "及其扩展赋值运算符

39.左值
  能出现在赋值表达式左边的表达式。

40.右值
  能出现在赋值表达式右边的表达式。

41.运算符的结合性
  指表达式中出现同等优先级的操作符时该先做哪个的规定。

42.位运算符
  " & "," | " , " ^ "," >> "," << "

43.逗号运算符
  即" , "

44.逻辑运算符
  " && ", " || " ," ! "

45.关系运算符
  ">",">=","<=","< "," <= ","== "

46.new运算符
  对象创建的操作符。

47.delete运算符
  对象释放操作符,触发析构函数。

48.内存泄露
  操作堆内存时,如果分配了内存,就有责任回收它,否则这块内存就无法重新使用,称为内存泄漏。

49.sizeof运算符
  获得对象在内存中的长度,以字节为单位。

50.表达式
  由操作符和标识符组合而成,产生一个新的值。

51.算术表达式
  用算术运算符和括号将运算对象(也称操作数)连接起来,符合C++语法规则的式子。

52.关系表达式
  用关系运算符和括号将运算对象(也称操作数)连接起来,符合C++语法规则的式子。

53.逻辑表达式
  用逻辑运算符和括号将运算对象(也称操作数)连接起来,符合C++语法规则的式子。

54.赋值表达式
  由赋值运算符将一个变量和一个表达式连接起来,符合C++语法规则的式子。

55.逗号表达式
  由逗号操作符将几个表达式连接起来,符合C++语法规则的式子。

56.条件表达式
  由条件运算符将运算对象连接起来,符合C++语法规则的式子。

57.语句
  在函数中控制程序流程执行的基本单位,如if语句,while语句,switch语句, do语句, 表达式语句等。

58.复合语句
  封闭于大括号{}内的语句序列。

59.循环语句
  for 语句, while 语句, do 语句三种。

60.条件语句
  基于某一条件在两个选项中选择其一的语句称为条件语句。

61.成员函数
  在类中说明的函数称为成员函数。

62.全局函数
  定义在所有类之外的函数。


63.main函数
  由系统自动调用开始执行C++程序的第一个函数  

64.外部函数
  在定义函数时,如果冠以关键字extern,表示此函数是外部函数。

65.内联函数
  在函数前加上关键字inline说明了一个内联函数,这使一个函数在程序行里进行代码扩展而不被调用。这样的好处是减少了函数调用的开销,产生较快的执行速度。但是由于重复编码会产生较长代码,所以内联函数通常都非常小。如果一个函数在类说明中定义,则将自动转换成内联函数而无需用inline说明。

66.函数重载
  在同一作用域范围内,相同的函数名通过不同的参数类型或参数个数可以定义几个函数,编译时编译器能够识别实参的个数和类型来决定该调用哪个具体函数。需要注意的是,如果两个函数仅仅返回类型不同,则编译时将会出错,因为返回类型不足以提供足够的信息以使编译程序判断该使用哪个函数。所以函数重载时必须是参数类型或者数量不同。

67.函数覆盖
  对基类中的虚函数,派生类以相同的函数名及参数重新实现之。

68.函数声明
  在C++中,函数声明就是函数原型,它是一条程序语句,即它必须以分号结束。它有函数返回类型,函数名和参数构成,形式为:
  返回类型 function (参数表);
参数表包含所有参数的数据类型,参数之间用逗号分开。如下函数声明都是合法的。
  int Area(int length , int width ) ;
或 int Area ( int , int ) ;

69.函数定义
  函数定义与函数声明相对应,指函数的具体实现,即包括函数体。如:
  int Area( int length , int width )  
  {
   // other program statement
  }

70.函数调用
  指定被调用函数的名字和调用函数所需的信息(参数)。

71.函数名
  与函数体相对,函数调用时引用之

72.函数类型
  (1) 获取函数并返回值。
  (2) 获取函数但不返回值。
  (3) 没有获取参数但返回值。
  (4) 没有获取参数也不返回值。

73.形式参数
  函数中需要使用变元时,将在函数定义时说明需要接受的变元,这些变元称为形式参数。形式参数对应于函数定义时的参数说明。其使用与局部变量类似。

74.实际参数
  当需要调用函数时,对应该函数需要的变元所给出的数据称为实际参数。

75.值传递
  函数调用时形参仅得到实参的值,调用结果不会改变实参的值。

76.引用传递
  函数调用时形参为实参的引用,调用结果会改变实参的值。

77.递归
  函数的自我调用称为递归。每次调用是应该有不同的参数,这样递归才能终止。

78.函数体
  与函数名相对,指函数最外边由{}括起来的部分。

79.作用域
  指标识符在程序中有效的范围,与声明位置有关,作用域开始于标识符的生命处。分:局部作用域,函数作用域,函数原型作用域,文件作用域,类作用域。

80.局部作用域
  当标识符的声明出现在由一对花括号所括起来的一段程序内时,该标示符的作用域从声明点开始到块结束处为止,此作用域的范围具有局部性。

81.全局作用域  
  标识符的声明出现在函数,类之外,具有全局性。

82.类作用域
  指类定义和相应的成员函数定义范围。

83.全局变量
  定义在任何函数之外,可以被任一模块使用,在整个程序执行期间保持有效。当几个函数要共享同一数据时全局变量将十分有效,但是使用全局变量是有一定弊端的:全局变量将在整个程序执行期间占有执行空间,即使它只在少数时间被用到;大量使用全局变量将导致程序混乱,特别是在程序较复杂时可能引起错误。

84.局部变量
  定义在函数内部的变量。局部变量只在定义它的模块内部起作用,当该段代码结束,这个变量就不存在了。也就是说一个局部变量的生命期就是它所在的代码块的执行期,而当这段代码再次被执行时该局部变量将重新被初始化而不会保持上一次的值。需要注意的是,如果主程序和它的一个函数有重名的变量,当函数被调用时这个变量名只代表当前函数中的变量,而不会影响主程序中的同名变量。

85.自动变量
  由auto修饰,动态分配存储空间,存储在动态存储区中,对他们分配和释放存储空间的工作是由编译系统自动处理的。

86.寄存器变量
  存储在运算器中的寄存器里的变量,可提高执行效率。

87.静态变量
  由连接器分配在静态内存中的变量。

88.类
  一种用户自定义类型,有成员数据,成员函数,成员常量,成员类型组成。类是描叙C++概念的三个基本机制之一。

89.外部变量
  由extern修饰的变量

90.堆
  即自由存储区,new 和delete 都是在这里分配和释放内存块。

91.栈
  有两个含义:(1)指内存中为函数维护局部变量的区域。(2)指先进后处的序列。

92.抽象类
  至少包含一个纯虚函数的类。抽象类不能创建对象,但可以创建指向抽象类的指针,多态机制将根据基类指针选择相应的虚函数。

93.嵌套类
  在一个类里可以定义另一个类,被嵌入类只在定义它的类的作用域里有效。

94.局部类
  在函数中定义的类。注意在函数外这个局部类是不可知的。由于局部类的说明有很多限制,所以并不常见。

95.基类
  被继承的类称为基类,又称父类、超类或范化类。它是一些共有特性的集合,可以有其它类继承它,这些类只增加它们独有的特性。  

96.派生类
  继承的类称为派生类。派生类可以用来作为另一个派生类的基类,实现多重继承。一个派生类也可以有两个或两个以上的基类。定义时在类名后加":被继承类名"即可。

97.父类
  即基类。见95基类的解释。

98.子类
  即派生类。见96派生类的解释。

99.对象
  有两重含义:
  1. 内存中含有某种数据类型值的邻近的区域。
  2. 某种数据类型的命名的或未命名的变量。一个拥有构造函数的类型对象在构造函数完成构造之前不能认为是一个对象,在析构函数完成析构以后也不再认为它是一个对象。  

100. 数据成员
  指类中存储数据的变量。

101.实例化
  即建立类的一个对象。

102.构造函数
  是一个类的实例的初始化函数,将在生成类的实例时被自动调用,用于完成预先的初始化工作。一个类可以有几个构造函数,以不同的参数来区别,即构造函数可以被重载,以便不同的情况下产生不同的初始化;也可以没有构造函数,此时系统将调用缺省的空构造函数。需要注意的是构造函数没有返回类型。

103.成员初始化表
  成员初始化表可用于初始化类中的任何数据成员,放在构造函数头与构造函数体之间,用":"与构造函数头分开,被初始化的数据成员的值出现在一对括弧之间,它们之间用逗号分开。

104.析构函数
  是一个类的实例的回收函数,将在该实例结束使用前被自动调用,用于完成资源的释放。一个类只可以有一个析构函数,当析构函数执行后,该实例将不复存在。析构函数同样没有返回值。

105.虚析构函数
  由virtual 修饰的析构函数,当用基类指针释放派生类对象时可根据它所指向的派生类对象释放准确的对象。

106.继承
  面向对象的程序设计语言的特点之一。即一个对象获得另一个对象的特性的过程。如将公共属性和服务放到基类中,而它的各派生类除了有各自的特有属性和服务外还可以共享基类的公共属性和服务。这样的好处是容易建立体系,增强代码重复性。

107.单继承
  一个派生类只有一个基类,成为单继承。

108.重继承
  一个派生类拥有多个基类,成为多继承。

109.虚函数
  在基类中说明为virtual并在派生类中重定义的函数。重定义将忽略基类中的函数定义,指明了函数执行的实际操作。当一个基类指针指向包含虚函数的派生对象时,C++将根据指针指向的对象类型来决定调用哪一个函数,实现了运行时的多态性。这里的重定义类似于函数重载,不同的是重定义的虚函数的原型必须和基类中指定的函数原型完全匹配。构造函数不能是虚函数,而析构函数则可以是。  

110.纯虚函数
  在基类中只有声明没有实现的虚函数。形式为:
  virtual type funname(paralist)=0。这时基函数只提供派生类使用的接口,任何类要使用必须给出自己的定义。

111.多态性
  给不同类型的实体提供单一接口。虚函数通过基类接口实现动态多态性,重载函数和模板提供了静态多态性。

112.复制构造函数
  以自身类对象为参数的构造函数,如Z::Z(const Z&). 用在同类对象间进行初始化。

113.运算符重载
  C++中可以重载双目(如+,×等)和单目(如++)操作符,这样可以使用户像使用基本数据类型那样对自定义类型(类)的变量进行操作,增强了程序的可读性。当一个运算符被重载后,它将具有和某个类相关的含义,同时仍将保持原有含义。

114.静态成员函数
  成员函数通过前面加static说明为静态的,但是静态成员函数只能存取类的其他静态成员,而且没有this指针。静态成员函数可以用来在创建对象前预初始化专有的静态数据。

115.静态成员变量
  在成员变量之前加static关键字将使该变量称为静态成员变量,该类所有的对象将共享这个变量的同一拷贝。当对象创建时,所有静态变量只能被初始化为0。使用静态成员变量可以取代全局变量,因为全局变量是违背面向对象的程序设计的封装性的。

116.私有成员
  只能由自身类访问的成员。

117.保护成员
  只能由自身类及其派生类访问的成员。

118.友元
  被某类明确授权可访问其成员的函数和类。

119.友元函数  
  在函数前加上关键字friend即说明了一个友元函数,友元函数可以存取类的所有私有和保护成员。友元在重载运算符时有时是很有用的。

120.友元类
  被某类明确授权可访问其成员的类

121.例外处理
  报告局部无法处理某错误的基本方式。由try., throw , catch组成。

122.文件
  是用于从磁盘文件到终端或打印机的任何东西。流通过完成打开操作与某文件建立联系。
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-5-4 19:03

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表