最近在为团队的大二本科生做培训,其实一直都有对他们进行指导,但是一个人真的挺累的,不过我还是把这个任务当成对自己的一次历练吧,说不定以后会因为有管理团队经验而出人头地呢,呵呵,幻想一下。要为他们讲课所以就需要备课,包括:C++,MFC和OpenCV的内容,其实这些东西自己都还算了解,不过乘着这次机会,还是好好的来个总结吧。
1. cin可以用来输入,但是如果我输入的一个字符串中有个空格符,那么它只能存入第一个空格前的部分,所以这个时候可以用gets()函数,它在<cstdio.h>头文件中。
2. strcpy,strcat,strcmp,strlen(返回的是字符的长度,不包括终止符),toupper,tolower,islower,isupper。但是要包含<cstring.h><cctype.h>头文件。
3. 数组的使用可以有声明或者无声明,例如int array[4][2]={{1,2},{1,2},{1,2},{1,2}},或者int array[][]={{1,2},{1,2},{1,2},{1,2}}。
4. 不要在使用指针时用类型转换,往往得不到正确的结果。
5. 关于main函数的传参数,如果要传包含空格的字符串那么得用双引号括起来。atof,atol,atoi将参数从字符串转换成float,long,int。
6. Call-by-value和Call-by-reference。Int f(int &i)将告诉编译器自动选择Call-by-reference方式。如果此时还传递个指针参数或者&型参数那么将报错。
注:如果引用的是函数内的局部变量,并将其进行引用返回,那么会出错,因为该变量已经在作用域内消失了。
7. Independent引用,建议一般不用,这样会使程序混乱。即是int j;int &i=j;。
8. 对于引用的几点要求:
9. 函数的重载和重写。各个重载函数的区别在于参数类型和个数,返回值并不能产生重载效果。
10. 对于重载要注意模棱两可的情况。如果存在f(float f)和f(double d),那么f(1.0)将执行的是f(double d),但是如果是f(1)那么将提示错误。同样的错误还有f(char)和f(unsigned char),f(int i)和f(int I, int j=1)等情况。
11. volatile是说一个变量可能会被意想不到的改变,所以要求编译器每次都小心的读取这个变量,而不是保存在寄存器里面。auto是默认的变量前缀。如果在每一个文件中都声明所需要的全局变量那么会产生错误,因为发现变量在多处被声明,这种情况就需要用extern来表示,用来创建个模型而不是创建个变量即是不分配内存。static是一定条件下永久存在的,因为为其分配了固定的存储单元,但是其作用域还是分local和global,在作用域外是不能访问它们的。经常使用的变量声明成register有助于提高效率,例如for循环内的i和累加器count、sum等。对于枚举类型enum type-name{value-list}variable-list,起始是0,如果其中一个被定义那么后面的值进行累加,尽管枚举类型被自动转换成integer但是从integer不能自动转换成enum。
12. 若要用到其它语言的函数,可以用extern “C” void myCfunc();来表示或者用extern “language” {prototypes}来表示多个函数。
13. 括号操作符,例如var={count=19,incr=10, count+1}最后得到的var结果是20。
14. MyClass ob = 5;等同于MyClass ob(5);,但是这种方式只对一个参数的函数有效。
15. inline内联函数有利于提高系统效率,因为在每次调用函数的时候,一系列的指令需要被执行,包括把参数放进堆栈或者从函数返回结果等,在很多情况下,CPU都被用来做这些事而不是用来计算。如果函数被声明为inline那么函数内的代码将在被用的时候直接被拷过来而不是去调用,省去了相当多的过程,但是这仅限于代码不多的函数。有几种情况下inline是不适用的:
16. 在类里面定义的函数将自动的被转换为inline函数,不需要自己加上inline标识符。
/******************************* 1月13日更新***********************************/
17. 类对象数组初始化MyClass obs[4]={-1, -2, -3, -4}或者MyClass obs[4]={MyClass(-1), MyClass(-2), MyClass(-3), MyClass(-4)}。
18. 相同类型的两个类可以将一个对象赋值到另一个对象,ob1=ob2。
19. 若将类作为参数传递给函数,那么在函数体内将为这个类对象产生一个赋值体,这样就会产生一个构造函数而多个析构函数的现象。这是因为传参的类对象并不会去调用构造方法来构造一个新的类对象,而是调用类的拷贝构造函数,如果没有定义该类的拷贝构造函数,那么编译器会替你生成一个默认的拷贝构造函数。
20. 若要返回个类对象,那么会为这个返回值建一个缓存值,当这个值返回后就销毁这个缓存。
21. 存在一个问题:当一个函数里面的对象在函数结束后需要调用析构函数来释放它所拥有的资源,这样就会产生原本不应该释放的资源被局部变量所释放,从而影响前面的对象。一种解决方法是将对象引用作为参数;另外一个是在拷贝构造函数里面为当前的局部变量创建空间,这样在析构函数中释放的就是当前申请的资源。
22. 拷贝构造函数就是用已经存在的类来初始化当前要定义的类对象,使用形式为MyClass(MyClass &ob)。
/******************************* 1月16日更新***********************************/
23. 友元函数不一定是类的成员函数,它可以在类结构外面定义,但是可以访问声明此友元函数的类中私有变量。当然友元函数也可以是一个类的成员函数而在另一个类中进行友元声明,例如friend bool MyClass::frdFunc(ThisClass ob)。友元函数的作用是可以将两个独立的类联系起来。
24. union和struct和类很像,它们来源于C语言但是又与C语言中的有差别(struct没有差别)。union是什么还记得吗,不记得了的话那么就赶快去回忆回忆吧(它表示几个变量共用一个内存位置,其长度为union中最大的变量长度,可以定义成数组和指针)。union和struct都是由多个不同的数据类型成员组成,但是在同一时刻,untion只存放了一个被选中的成员,对于不同成员的赋值将会对其它成员造成重写的后果,原来成员的值就不存在了。在C++中union还可以拥有成员函数和构造及析构函数。但是这并不意味着你就必须去使用union了(不是很推荐),因为在使用union时有以下几条需要注意:
25. 匿名union使用就不用“.”操作符了,但是需要注意不能跟其它关键字或者标识符搞混淆。
26. 类中的成员函数都默认的含有个this指针。类外的友元函数中不含this指针,毕竟它不是类的成员函数。
27. 注意操作符重载而不是重写。作为成员函数的操作符重载,第一个参数默认的是this指针,后面参数手动输入,最好返回第一个参数的参数类型。作为非成员函数的操作符重载一般是友元函数,用作全局的比较少也不安全。
28. 在C语言中学过“++”和“--”操作符支持左处理(a++)和右处理(++a),普通的operator操作符重载只能达到右处理的功能,要完成左处理的功能需要用MyClass operator++(int notused)。如果“++”在标识符的前面那么operator()被调用,否则operator++(int notused)被调用。
29. 关于非成员变量的操作符重载函数,一般使用形式为friend,由于其不含默认this指针所以需要添加第一和第二操作数参数。这种形式的用处不大,除了一种情况,例如,对于类成员操作符重载函数而言,myClass=myClass+10;是正确的表达,但是myClass=10+myClass;却会产生错误,因为第一参数默认的是this所指向的类对象,而10是标准数据类型,这种时候就可以使用friend的操作符重载函数来解决。同时,还要注意的是,对于需要修改值的operator,friend形式要传入引用参数MyClass &ob。