• C++常见问题解答


    C++常见问题解答 
    引言篇 
    1.学习C++是否必须先了解C? 2.怎样开始学习C++? 
    3.改进C++程序的最好方法是什么? 4.对于小的程序C优于C++,对吗? 5.C是C++的子集吗? 
    6.C++与C有什么区别? 
    7.为什么用C++产生的"Hello World"的程序代码要比用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.如何判断文件结束? 提高篇  
    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++中可以嵌入汇编吗?  
    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++程序包括哪几部分? 
      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有哪些优点? 
      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++程序中嵌入汇编代码将会大大提高程序的效率。

  • 相关阅读:
    岳麓山岳麓书院
    花洲书院
    《诫子书》诸葛亮
    AI ML DL
    台湾大学林轩田机器学习基石
    LeNet
    VGGNet
    AlexNet 2012
    AS 中 Plugin for Gradle 和 Gradle 之间的版本对应关系
    AndroidStudio、gradle、buildToolsVersion关系
  • 原文地址:https://www.cnblogs.com/fvsfvs123/p/3107522.html
Copyright © 2020-2023  润新知