第2章 开始学习C++

来源:互联网 发布:电脑远程连接软件 编辑:程序博客网 时间:2024/05/18 03:30
1:  C++中的函数可以被其他函数激活或调用,那么问题来了,main()函数是由谁调用的?我们可以看到,在很多代码中,main函数是如下这样写的    int main(int argc, char *argv[])    argc与argv这两个形参定义到底是给谁写的?    通常,main()函数被【启动代码】调用,【启动代码】是由编译器添加到程序中的,是程序与操作系统之间的桥梁。    事实上,这种函数头描述的是main()函数与操作系统之间的接口。    可以简单的理解为对应于argc与argv的实参是操作系统发送给main()函数的2:  在C语言与C++语言对于函数头中形参列表中的void的解读是不一样的,假如我们自定义了一个叫function的函数,程序的代码如下:    ...    int function(void);    ...        int main(void)    {        ....        function(1,2,3,4);        ....        return 0;    }        int function(int a, int b)    {        ....;        ....;    }        在C语言中,上面这句函数原型表达的意思是:程序员告诉编译器,我自定义了一个函数叫做function,但是这个函数到底接受不接受参数,接受什么类型、多少个参数,我没说,编译器同志,你需要自己去看函数的定义。这会造成一种尴尬的情形,就是上面代码所示的那样,调用function()的时候程序员传进了参数,编译器看到这里的时候,并不知道参数传的是否正确,因此可能并不会报错,但是当编译器看到函数定义的时候,才仰天长叹艹泥码,孙子你玩我,然后程序就挂了。    而在C++中,上面这句函数原型表达的意思是:程序员告诉编译器,我自定义了一个函数叫做function,它不接受任何参数!!!,也就避免了上面那种尴尬的情形。    从中可以看出,两种语言关于函数原型的形参列表中void的解读是不一样的。    延伸一点,其实两种语言对于函数定义时形参列表中的void的解读也是不一样的。    C语言依旧认为,不确定该函数是否接受参数,如果程序员硬要作死传递给该函数几个参数,编译器也不会报错。    而C++则认为,该函数不接受任何参数,任何企图传递参数的行为都是错误的。    这个知识点其实没什么用处,了解一下即可。3:  是否所有的C/C++程序都需要main()函数?    不一定,在Windows编程中,可以编写一个动态链接库(DLL)模块,这是其他Windows程序可以使用的代码。由于DLL模块不是独立的程序,因此,这种程序不需要main()函数4:  #include <iostream> 这句话是什么意思?为什么这行语句结束不需要分号?    C/C++中,带#的语句被称为【预编译指令】,程序在编译时,先是将代码提交给【预编译器】,然后才进行真正意义上的编译,【预编译器】负责处理包括带#语句在内的所有预编译指令    而#include <iostream> 这句话经过预编译器处理后,就是将这句话机械的替换为【iostream】文件中的文本    其实就是替换    5:  C与C++的头文件的区别    在C++中可以包含所有C语言用的头文件,这些头文件以.h为文件扩展名,毕竟C++是C的一个超集,所有在C中的行为在C++中几乎都是可以原样实现的    C++自身特有的头文件没有扩展名,如<iostream>    而C++对于原有的C语言.h头文件,也有对应的无扩展名版本,内容几乎一致,名称是原.h头文件的文件名前加一个c(小写),如<cstdio><cmath><cstring>等6:  为什么C++要使用【名称空间】这样的概念?    是为了防止两个公司写的代码中,有完全相同的两个函数出现,比如有A公司与B公司,都写了一个叫func()的函数,可怕的是,这两个函数的参数列表与返回值类型都一致,无法通过函数重载来区别它们    为了区别这两个公司写的函数,就将A公司的函数放在A名称空间中,将B公司的函数放在B名称空间中,于是,这两个函数的全称应该是    A::func()    B::func()    如果想省略A::或B::,要显式的说明【运用A/B名称空间】,语句如下    using namespace A;    using namespace B;    using namespace std;    //  使用std名称空间    cin 与 cout都在std名称空间下    名称空间声明的效力只在当前的作用域,可以理解作用域为{}括起来的范围,如果在{}之外,那么该作用域就是这个代码文件本身    7:  cout与cin到底是什么?    cout是一个预定义的对象,所谓预定义,是指不象变量或类对象一样需要声明或定义,cout是被预先定义好的,这个对象对于程序员来说,始终都是存在的,你不需要去了解它是在什么地方声明的    既然cout是一相对象,那么,它是哪个类的对象?答案是ostream类    相对的,cin是istream类的对象,也是预定义的对象        cout作为对象来讲,可以简单的理解为cout是C语言中的stdout,是一个输出流,这个流通过<<操作符来将消息接收,或者说消息通过<<操作符发送给输出流    相对的,cin是通过>>操作符将流中的内容取出来,给变量        而>>与<<本身是右移和左移操作符,在istream与ostream中,这两个操作符被重载了,所以才有上述的功效    所谓操作符重载,是指人为的自定义在一定上下文环境中,某个操作符的行为,比如通过重载+操作符,可以实现两个结构体相加,或者其他    关于操作符重载,在后面的章节会详细涉及    8:  endl与'\n'的区别    endl是一个符号,但不是一个字符,这个符号的名字叫做控制符(manipulator),将这个符号发送给输出流对象cout的话,会令流中的光标挪到下一行    而'\n'则是一个字符,这个字符显示出来就是一个换行的效果,不,这么描述并不正确,其实这个字符“打印”出来并不是字符,而是一种效果,这种效果就是:让光标挪到下一行    关注这种区别有意义吗?答案是没有!了解一下就可以了9:  wihlte space指的是三类字符:【空格】【制表符】【回车】10: C++中的新特性,连续赋值    int a;     int b;    int c;    a = b = c = 4;    这种语句对于C++来说是完全合法的,赋值是从右到左进行的,过程是:将4赋值给c,再将c赋值给b,再将b赋值给a,最终的结果是,三个变量的值都是4    要注意的是,这其实是C++的新特性,你可能会疑惑,我学C语言的时候这么写过千百回了,怎么就成了【新特性】呢?    真相是,这种赋值语句在C语言中其实是非法的,而你学习C语言的时候,用的编译器其实是C++的编译器,或者说你用的编译器号称自己是C语言的编译器,但是已经支持了这种C语言标准中没有说明的特性    你用古老的TC试试,绝对是报错的11: C++的cout与C的printf()之间的优劣性    cout其实相较于printf()来说是相当方便的,cout会自动识别<<操作符后边的值的类型,并给出正确的输出    但对于熟悉C语言的人来说,进行格式化输出的时候,用printf()或许更得心应手一些,但这并算不上是printf()的优势,因为用cout也可以比较方便的进行格式化输出,只是相较于printf()而言,设置格式的过程没有用%....之类的控制字符串设置起来直观,这个在后面章节会讲到    所谓格式化输出,就是将5输出成005.00,将8.321486输出成+8.32,限制每个数字占多少个位置,右对齐还是左对齐之类的输出。这种输出方式在没有图形界面的时候显得很重要,但是对于今天的程序设计来说,并不显得那么重要,所以cout更适合今天的程序员写今天的代码。    cout对于printf()最大的优势就是,<<操作符是可以重载的!!!你新建一个类、结构体、抽象数据类型,如果用printf()来输出的话,通常的作法是写一个函数来进行输出,而运用cout,可以将<<重载之后,就可以按你的需求来显示自定义类的具体对象了,使cout可以识别和显示所开发的新的数据类型。    使用更方便,简直Excellent!12: 什么是类?什么是面向对象?    类,是用户定义的一种数据类型。类不光描述了数据类型所存储的信息,更重要的是,它描述了可以在这种数据类型上执行的操作,这是面向对象的重要思想。    在面向过程的C语言中,我们写一个链表,方式是写一个结构体,然后写一大堆函数,用一个指向头结点的指针来代表这个链表    对这个链表进行操作的时候,是如下这样写的:    InitList(L);    DeleteNode(L,5);    InsertNode(L,7,9);    MergeList(L1, L2);    而在面向对象的C++中,我们可以写一个类,这个类中描述了什么是链表,重要的是,这个类描述了可以在链表上执行的操作,假设这个类名叫做LinkList,那么相对于上面的代码,在C++中是这么写的    LinkList L;         // 创建一个LinkList类的对象(实例),名叫L    L.Init();    L.DeleteNode(5);    L.InsertNode(7,9);    L1.Merge(L2);        在面向过程思想中,我们定义一大堆过程,这些过程就是C语言中的函数。    有的过程需要一些数据作为原料,对这些数据进行加工,产出一个结果。这些原料数据叫做函数的参数,在函数的形参列表中声明了原料的类型,加工出的结果称为返回值。    程序是由各种过程与参与其中的数据组成。    就像生产手机的富士康,一个个车间流水线就是一个个过程,生产原料与工人就是参数,A车间的流水线加工出的产品(返回值),作为B车间的原料(参数)。。一直这样运行下去,最终加工出手机。    而对应的程序就是将一个个车间流线的过程描述成函数,生产原料与工人就是变量或常量(数据),在主函数中声明变量,写明常量(招工人,买原料),然后用一个又一个函数将程序将手机的制作过程描述出来。        而在面向对象中,其设计思想并不将程序理解为一大堆“过程”或“步骤”,而是将程序拆分为对象,多个对象协作起来,就叫程序,程序就是描述这些对象协作的方式的。    同样是富士康的例子,在面向对象的程序里,可以说每个功能车间都是一个类。    实现手机需要两个A车间造板子,一个B车间造屏幕与其他构件,一个C车间装配,OK,我们声明两个A类的对象a1,a2,声明一个B类的对象b,一个C类的对象c。    创建对象时,其内部的数据(工人与原料)就配好了(类的构造函数),如果对a1车间某个工人不满意,OK,可以通过a1的换人成员函数将新的工人送进去,a2的生产速度要降低,OK,将消息传递给a2的生产速度成员函数    而对于对象c,可以将a1,a2,b作为消息传递给c的构造函数(也是成员函数),将c完成装配,然后,c通过它的一个出厂成员函数将手机扔出来。        所以说面向对象并不是完全不描述过程,只是用这种方式能将程序拆分成更大的模块,各个模块之间的独立性也更强,使复杂的程序设计在逻辑上变得清晰,使软件工程在设计、管理等方面更规矩,从而变得高效而又健壮。        而C++强大的地方并不只是面向对象,C++强大的地方在于,对于复杂的程序设计,程序员可以用面向对象的设计模式,而对于一些小的程序设计,使用面向对象的思想设计程序可能会使软件开发的工作量更大,这个时候,程序员依然可以使用面向过程的设计模式。    在面向过程的领域中,C++有更多的新特性,是的,比C更复杂,但也更简捷。    在面向对象的领域中,C++又比其它面向过程的语言的执行效率更高。    这也是有代价的,代价就是,当用C++写复杂度过于高的程序时,各种类之间乱七八糟的继承,各种乱七八糟的接口,调试程序会让程序员觉得自己是在屎山上游泳。13: C++与C一样,不允许将函数定义嵌套在另一个函数定义中,每个函数定义都是独立的,所有的函数创建都是平等的。14: main()函数的返回值到底是干什么用的?    答案是,可以将计算机的操作系统看作main()函数的调用程序。因此,main()的返回值并不是返回给程序的其他部分,而是被返回给操作系统。很多操作系统都可以使用程序的返回值。如,UNIX外壳脚本和DOS批处理文件都被设计成运行程序,并测试它们的返回值(通常叫做退出值)。通常的约定是,退出值为0则意味着程序运行成功,正常结束,非0则意味着存在问题,程序非正常结束。    所以在一些程序中,会在一定条件下让main()返回非0值,诸如打开文件失败之类的。。15: main其实不是C++/C的关键字,不过,它是一个必不可少的函数的名称,其实是可以将main这个单词用作变量名的,诸如自定义函数的定义中,可以写一个变量名叫做main,但最好不要这么做,这样做除了添乱之外,没有什么好处

0 0