您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 数据通信与网络 > C++高级编程课程讲义
C++高级编程OverviewModule1:面向过程的C++Module2:面向对象的C++Module3:C++设计模式Module1:面向过程的C++从C到C++内存管理数组字符集和字符串指针和引用函数其它从C到C++语法增强新的运算符变量声明更加灵活函数重载引用类型安全性面向对象封装继承多态内存管理在stack上分配内存简单数据类型不使用new创建对象实例函数调用完成自动销毁线程堆栈的限制在Heap上分配内存malloc还是new?检测内存泄漏防止”野指针”:回收内存后指针会自动为NULL吗?Demo:动态扩充的字符串缓冲区数组(1)声明及初始化inta[]={1,2,3};intb[3]={1,2,3};intc[5]={1,2,3};//c[3]和c[4]的值默认为0inta1[2][3]={{1,2,3},{4,5,6}};inta2[2][3]={{1},{}};//初始化,第一行为1,0,0;第二行为0,0,0inta3[][3]={{},{1,2,3}};inta4[2][]={{1,2,3},{4,5,6}};//错误。必须声明第二维的数目inta5[][3]={1,2,3,4,5,6};//正确数组(2)数组的内存形式数组在内存中的存放全局数组在静态存储区域中存放局部数组,一般在堆栈上存放在堆上动态分配内存线程堆栈的限制:doublearr[500][300]?double*p=newdouble[10];intn=10;double*p=newdouble[n];//n不必是常量double*p=newdouble[400][300];//错误double**p=newdouble[400][300];//错误数组(3)指针表现形式一维数组指针表示二维数组指针表示行地址和列地址constintARRAY_SIZE=5;inta[ARRAY_SIZE]={1,2,3,4,5};int*p=a;考察:(1)a+i,p+i,*(a+i),*a+i,p[i]的含义(2)p++偏移几个字节?a++呢?inta[][3]={{1,2,3},{4,5,6}};考察:a,a+i,*(a+i),*(a+i)+j,*(*(a+i)+j),&a[i][j]的含义数组(4)二维数组的指针表示使用一级指针访问二维数组使用指向一维数组的指针来访问二维数组inta[][3]={{1,2,3},{4,5,6}};int*p=a[0];//将二维数组展开成一维数组的方式访问int*p=a;//错误!考察:p+i,*(p+i),*p+i的含义int(*p)[3]=a;//也可写成:int(*p)[3](a);int*p[3]=a;//错误!Int*p[3];考察:p,p+i,*(p+i),*p+i,*(p+i)+j,*(*(p+i)+j)的含义数组(5)动态创建复杂数组二维数组交错数组intm=2;intn=3;int(*p)[3]=newint[2][3];delete[]p;int*p[2];//p数组包含两个元素,每个元素都是int*类型p[1]=newint[3];//通过p[i]来操作每个数组delete[]p[1];//不能使用deletep或者delete[]p字符集和字符串(1)字符编码ANSI、UNICODE和UTF-8MultiByte和WideCharwchar_t,“L”前缀,wcslen,wcscpy,wcslen字符集的转换mbstowcs_s和wcstombs_sMultiByteToWideChar,WideCharToMultiBytewchar_tp1[]=L“abcd”;考察:wcslen(p1)和sizeof(p1)的结果wchar_tp1[]=Labcd;charp2[10];intlen=wcstombs(p2,p1,sizeof(p1));//len=4‟\0‟字符不计入拷贝字符数目wchar_t*p3=(wchar_t*)malloc(100);mbstowcs(p3,p2,100);字符集和字符串(2)兼容字符集Windows平台与字符集VisualC++编译器字符集设置选项_UNICODE_MBCS兼容字符集TCHAR,_tcslen,“_T”TCHARt[]=_T(aaa);//如果编译器定义了_UNICODE,sizeof(t)=8,//如果定义了_MBCS,sizeof(t)=4字符集和字符串(3)声明字符串使用指针使用数组char*p1=abcd;char*p2=abcd;考察:内存中有几个”abcd”存在,p1==p2是否成立?charp1[10]={„a‟,„b‟,„c‟,„d‟,„\0‟};//注意结尾的‟\0‟charp2[]={“abcd”};//自动添加‟\0‟结尾charp3[]={“abcd”};charp4[]={'a','b','c','d'};//仅仅声明一个字符数组而非字符串考察(1)sizeof(p),strlen(p)的值分别是多少?(2)p2==p3?字符集和字符串(4)字符串操作函数修改单个字符字符串长度模拟编写strcpy方法为何采用const作为参数为何返回char*„\0‟会被拷贝吗?Democharp1[10]=“abcd”;char*p2=“abcd”;//p2指向常量字符串p1[0]=„x‟//OKp2[0]=„x‟//错误,常量字符串不可修改charp1[]=a\t\nc;考察:strlen(p1)和sizeof(p1)指针与引用(1)概念指针与指针变量引用的定义引用必须在声明时立即初始化,不允许空引用引用一旦初始化,就不能再引用其它数据引用和被引用的变量实际上代表同一个内存的数据doublea=10;double*p=&a;考察:(1)p是指针变量,则sizeof(p)=?(2)&p含义是什么?inta=100;int&b=a;b=1000;考察:(1)&a与&b的关系?(2)a=?指针与引用(2)混合使用指针指向某个引用引用一个地址doublea=100;double&b=a;double*p=&b;考察:(1)&a,p和&b的关系(2)修改a,b或*p的值,另两个是否联动doublea=100;double&b=a;double*p=&b;double*&rp=p;//p和rp是完全相同的,且都是变量a的地址考察:sizeof(b)=?sizeof(rp)=?指针与引用(3)作为参数传递按值传递按地址传递按引用传递voidIncrease(int&data){data++;}voidmain(){intmydata=10;Increase(mydata);}指针与引用(4)指针与常量指向常量的指针指针常量inta=100;intb=200;constint*pci=&a;//pci不能直接修改a地址中的数据a=1000;//可以通过修改a的数据从而间接修改*pci*pci=1000;//错误pci=&b;//OK.Pci可以指向另一个地址,不再与a相关考察:如果a被定义为:constinta=100,那么:int*pci=&a;是否成立?inta=100;intb=200;int*constpci=&a;//pci不能再指向别的地址*pci=1000;//可以通过修改*pci来修改a的数据pci=&b;//错误考察:如果有constint*constpci=&a,则情况如何?指针与引用(4)引用与常量将一个引用设置为常量后,不能通过该引用修改数据;但仍可通过被引用的变量来改变:被引用的数据是常量,引用本身也必须是常量:inta=100;constint&b=a;//b与a是同一内存,但不能直接修改bb=1000;//错误a=1000;//OKconstinta=100;constint&b=a;//OKint&b=a;//错误指针与引用(5)Practicechars1[]=abcdefg;chars2[]=1234567;char*p1=s1;constchar*p2=s1;char*constp3=s1;constchar*constp4=s1;考察:下列哪些语句有效:p1[0]=‟k‟;p2[0]=‟k‟;p3[0]=‟k‟;p1=s2;p2=s2;p3=s2;p4=s2;函数(1)ExternC语言中的Extern和StaticC++中的extern“C”允许在C++中调用C编写的函数允许在C中调用C++编写的函数Demo:如何在C++和C之间实现互操作cfile.h文件:externintadd(intx,inty)cfile.c文件:intadd(intx,inty){returnx+y;}cpp.cpp:extern“C”{#include“cfile.h”}……其它格式:extern“C”intadd(intx,inty);extern“C”{intadd(intx,inty);intsub(inta);}函数(2)函数指针声明原型指针赋值函数调用函数指针作为参数传递int(*fun)(intx,inty);或者int(*fun)(int,int);设存在函数intmax(inti,intj){……}int(*fun)(int,int)(max);或者fun=max;(*fun)(10,20);voidprocess(intx,inty,int(*f)(int,int)){……}process(10,20,max);函数(3)函数指针设有函数定义:intmyequal1(char*s1,char*s2){...}类型定义:typedefint(*equal)(char*,char*);则可以声明:equaleq=myequal1;并且调用:(*eq)(s1,s2);函数(4)缺省参数注意缺省参数必须出现在所有非缺省参数的后面防止函数重载时的二义性voidf(inti,intj=10,intk=20){……}调用:f(1,20),相当于:f(1,20,20)而:f(1),相当于:f(1,10,20)函数(5)参数个数不定回顾printf(“%s”,……)编写自定义得可变参数个数函数(stdarg.h)intaverage(intfirst,...){intcount=0,sum=0,i=first;va_listmarker;va_start(marker,first);while(i!=-1)//为方便起见,假定参数以-1结尾{//实际工作中应通过某种方式确定参数的个数sum+=i;//例如printf就是通过格式化串中的%确定的count++;i=va_arg(marker,int);}va_end(marker);return(sum?(sum/count):0);}其它sizeof针对字符串的sizeof针对数组和指针的sizeof针对结构体的sizeof变量赋值a=b=c=3?int*x,y?int*x,yconst和define作用域限定运算符无名共用体枚举Module2:面向对象的C++构造和销毁参数和返回值const修饰符运算符重载虚函数友元模板其它构造和销毁(1)数据声明和初始化数据类型不初始化的后果初始化位置类实例变量不确定值构造函数、拷贝构造函数类静态变量编译错误类声明外初始化函数内局部变量可能运行错误声明时初始化、使用前赋值函数内静态变量有默认值声明时初始化、赋值类实例常量编译错误构造函数初始化列表类静态常量编译错误声明时初始化、声明外初始化classA{public:A():d2(10){/*d2=10error!*/}staticintd1;//staticintd1=100;error!constintd2;//constintd2=10;err
本文标题:C++高级编程课程讲义
链接地址:https://www.777doc.com/doc-5593210 .html