面向对象程序设计(C++)课件全套 高洪皓 第1-10章 C++基本语法- C++新特性_第1页
面向对象程序设计(C++)课件全套 高洪皓 第1-10章 C++基本语法- C++新特性_第2页
面向对象程序设计(C++)课件全套 高洪皓 第1-10章 C++基本语法- C++新特性_第3页
面向对象程序设计(C++)课件全套 高洪皓 第1-10章 C++基本语法- C++新特性_第4页
面向对象程序设计(C++)课件全套 高洪皓 第1-10章 C++基本语法- C++新特性_第5页
已阅读5页,还剩748页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

大学计算机基础教学系列教材第一章C++基本语法2026年5月11日目录输入输出第1.1节bool类型第1.2节引用操作第1.3节函数重载第1.4节1234CONTENTS默认参数第1.5节for循环介绍第1.6节56Const修饰第1.8节7动态内存第1.9节89数组表示方法(string类型)第1.7节学习目标掌握C++的基础语法,涵盖输入输出操作、引用机制、函数重载、字符串处理、for循环结构以及动态内存管理等核心内容。了解C++相较于C语言新增的函数重载、引用传递及默认参数等特性。输入输出01第1.1节输入输出(C语言)

C语言的输入和输出函数归属于标准库,scanf函数负责输入操作,printf函数则负责输出操作,二者均需以格式字符串作为参数。

inta;scanf("%d",&a);//C语言读取整数printf("%d\n",a);//C语言输出整数输入输出(C++输入)

C++采用面向对象方法处理输入输出,通过流的概念实现。cin是输入流对象,用于从标准输入设备(通常指键盘)获取输入数据。cout是输输出流对象,将目标数据写入输出设备(通常指屏幕)cin>>a;cout<<a<<"\n";输入输出(C++)在C++语言中,采用iostream实现输入输出操作,其机制与C语言存在差异。C语言的I/O操作主要依赖包含stdio.h等头文件;而C++则引入了更完善的iostream标准库,提供了基于对象模型的输入输出流机制,具体体现为cin、cout、ifstream、ofstream等组件。C++中:所属位置:cout定义在<iostream>头文件中,且属于std命名空间。使用方式:直接使用,需加前缀,即std::cout。在文件开头添加#include<iostream>和usingnamespacestd;,可直接用cout。输入输出(C++)此外,C++流支持链式调用机制,允许在单一表达式内连续执行多个输出操作。例如:

#include<iostream>#include<string>usingnamespacestd;intmain(){inta;floatb;stringname;cin>>a>>b>>name;cout<<"输入的整数为"<<a<<endl;cout<<"输入的浮点数为"<<b<<endl;cout<<"输入的字符串为"<<name<<endl;//endl会输出一个换行符,并刷新输出缓冲区,确保所有的输出都被发送到屏幕return0;}12345.67Hello输入的整数为123输入的浮点数为45.67输入的字符串为Hello程序输出如下:1.当用户输入以下内容cin忽略空格自动识别空格123aHello2.讲b定义替换成charb呢?C++与C语言输出对比C++中cout在输出浮点数时,依据数值的具体内容选择最合适的格式。例如C++C语言#include<iostream>usingnamespacestd;intmain(){floata=12.0;cout<<a<<endl;return0;}#include<stdio.h>intmain(){doublea=12.0;printf("%lf\n",a);return0;}12.000000程序输出如下:12程序输出如下:C++与C语言输出对比C语言执行输入输出操作时系统不会自动刷新缓冲区这意味着数据可能在缓冲区中滞留,直至缓冲区满载或遇到特定控制字符(如换行符“\n”)时方被处理。#include<stdio.h>intmain(void){printf("Hello");/*少了一个\n*/for(;;);

/*死循环*/return0;}#include<stdio.h>intmain(void){printf("Hello\n");/*多了一个\n*/

for(;;);

return0;}看不到Hello输出看到Hello输出C++也同样需要\n或者endl刷新缓冲区。cout<<"Hello,world!"<<"\n";cout<<"Hello,world!"<<endl;//流操作符endl以表示输出结束

<iomanip>头文件<iomanip>是C++标准库中的一个头文件,用于格式化输入输出流。该头文件提供了一系列操作符,用于控制输入输出流的格式,包括:setprecision(intn):设置浮点数的精度。fixed:设置浮点数以固定的小数点格式输出。

scientific:设置浮点数以科学计数法格式输出。

setw(intn):设置下一个输出字段的宽度。

setfill(charc):设置填充字符。left与right:分别设置输出内容的左对齐与右对齐方式。<iomanip>操作通过使用<iomanip>库中的操纵符fixed和setprecision(),可对浮点数输出进行格式化处理。例如:#include<iostream>#include<iomanip>usingnamespacestd;intmain(){doublenum=123.456;cout<<fixed<<setprecision(2)<<num;return0;}123.46程序输出如下:同时,C++提供了左对齐的输出方式,可通过left操作符实现。例如:#include<iostream>#include<iomanip>usingnamespacestd;intmain(){stringstr1="hello";stringstr2="world";cout<<left<<setw(10)<<str1<<setw(10)<<str2<<endl;return0;}helloworld程序输出如下:字符串的输入与输出(C语言)在C语言中,gets与puts函数曾获广泛使用以处理字符串,然其因存在缓冲区溢出风险,现已视为存在安全隐患。gets函数用于自标准输入读取一行字符串,直至检测到换行符,并将该字符串存储于指定字符数组。puts函数用于向标准输出写入字符串,其不会在字符串末尾附加换行符。若字符串本身未包含换行符,输出后光标将滞留于行末。例如:

charstr[100];gets(str);//C语言读取字符串,注意:不推荐使用puts(str);//C语言输出字符串,注意:也不推荐使用字符串输入输出(C++)在C++语言中,getline函数用于从输入流读取整行字符串,为字符串读取操作提供了一种更安全的替代方案。getline()函数包含两个参数:输入流对象(如cin)存储输入字符串的string对象字符串输入输出(C++)C++语言则提供string类型实现字符串存储功能。getline函数将持续读取输入流直至检测到换行符`\n`,并将所读取内容(不含换行符)存入指定的string对象。例如:#include<iostream>usingnamespacestd;intmain(){stringstr;cout<<"输入一个字符串";getline(cin,str);//读取一整行输入,包括空格cout<<"您输入的字符串是"<<str<<endl;

return0;}bool类型0214第1.2节15bool类型简介C语言未定义布尔(bool)类型,一般以整型(int)表示布尔值。数值0对应逻辑假(false),非零整数对应逻辑真(true)。例如:而C++通过引入bool类型,提供true和false两个关键字,从而使布尔值的表示更为直观且安全。intisTrue=1;//C语言中表示trueintisFalse=0;//C语言中表示false16bool类型的申明和初始化在C++中,申明布尔类型的变量,可通过关键字bool后接变量名的方式实现。例如:bool类型的变量在使用前,必须对bool变量进行初始化。在初始化布尔类型变量时,可赋予true或false值。该两个取值为布尔类型仅有的两个可能取值。此外,在申明该变量时亦可进行初始化。例如:boolflag;boolstate=true;//state被初始化为trueboolstate=false;//state被初始化为false17bool类型的操作符和表达式在C++语言中,布尔(bool)类型提供三种基本逻辑操作符:&&(逻辑与)、||(逻辑或)和!(逻辑非)。&&操作符用于判断两个布尔表达式是否均为逻辑真。当两个操作数皆为真时,结果为真;否则结果为假。该操作符具有短路求值特性:若首个操作数为假,则不再对第二个操作数进行求值,因表达式结果已确定为假。例如:boola=true;boolb=false;boolresult=a&&b;//result为false,思考:result=b&&a;18bool类型的操作符和表达式||操作符用于判断其操作数中是否至少有一个布尔表达式的值为真。若任一操作数为真,则结果为真;若两操作数皆为假,则结果为假。该操作符同样具备短路逻辑特性:当第一操作数为真时,第二操作数将不被计算。例如:boola=true;boolb=false;boolresult=a||b;//result为true,因为a为true,不需要考虑b的值19bool类型的操作符与表达式!操作符用于对布尔表达式的逻辑值进行取反。若操作数为真,则结果为假;若操作数为假,则结果为真。该操作符属于单目操作符,仅作用于单个操作数。例如:逻辑操作符在C++中具备类型安全性,仅能对bool类型的操作数执行逻辑运算。此外,得益于“短路逻辑”机制,此类操作可显著提升程序执行效率,不必要的计算过程因此将被跳过。boola=true;boolresult=!a;//result为false20bool类型的隐示转换intmain(){boolisTrue=true;inta=isTrue;//isTrue被隐式转换为1boolisFalse=false;intb=isFalse;//isFalse被隐式转换为0if(a==1){cout<<"a由true转换而来,值为1"<<endl;}else{cout<<"a的值不是1,出现意外情况"<<endl;}

在C++中,bool类型支持隐式转换为整型(int),其中true值对应整型值1,false值对应整型值0。该隐式转换机制使得布尔值无需显式类型转换即可应用于需要整型数据的场景。if(b==0){cout<<"b由false转换而来,值为0"<<endl;}else{cout<<"b的值不是0,出现意外情况"<<endl;}return0;}引用操作0321第1.3节22引用的定义和特性在C++中,引用(Reference)作为一种特殊的数据类型,提供对另一变量的间接访问机制。该特性常用于函数参数传递、返回多个值及简化代码。引用作为变量的别名标识,须在申明时完成初始化操作。初始化后,其指向目标不可变更,即在引用的整个生命周期内始终绑定同一实体。申明引用时,需在变量类型后添加&符号。例如:int&ref=value;//ref是value的引用intvalue=10;intvalue1=5;intvalue2=20;int&ref=value1;//初始化引用//ref=value2;//如果尝试给ref重新赋值,编译错误,不能改变引用的指向目标23引用与指针的区别相较于引用固定绑定于特定对象的特性,指针可在运行过程中随时变更其指向目标。引用与指针虽均用于间接访问数据,但引用必须在申明时完成初始化操作。引用一旦申明即须绑定对象,此后该引用不可再重新指向其他对象。例如:intvalue=10;int&ref=value;//正确:引用在申明时被初始化//int&ref2;//错误:引用必须在申明时被初始化24引用与指针的区别因此引用的"指向"具有永久性,引用具有对象别名的语义特征,即引用与其所引用的对象之间形成不可分割的绑定关系。例如:intmain(){intvalue1=20;intvalue2=30;int&ref=value1;//ref引用value1cout<<"初始值:value1="<<value1<<",value2="<<value2<<endl;cout<<"初始值:ref="<<ref<<endl;ref=value2;cout<<"修改后:value1="<<value1<<",value2="<<value2<<endl;cout<<"修改后:ref="<<ref<<endl;//如果想让ref引用value2,必须在定义ref时就绑定://int&ref2=value2;return0;}初始值:value1=20,value2=30初始值:ref=20修改后:value1=30,value2=30修改后:ref=30程序输出如下:相比之下,指针可以随时被赋予一个地址,甚至在申明时不赋值,使用时按需赋值。例如:intvalue=10;int*ptr;//未初始化的指针ptr=&value;//稍后初始化指针25引用与指针的区别指针可随时变更所指向的对象。例如:voidmodifyByPointer(int*ptrValue);intmain(){intvalue1=10;intvalue2=20;//指针示例int*ptr=&value1;cout<<"初始时ptr指向value1,value1="<<value1<<endl;cout<<"初始时ptr指向value1,value2="<<value2<<endl;ptr=&value2;//指针可以改变指向*ptr=30;//通过指针修改value2的值cout<<"修改value2后,value1="<<value1<<endl;cout<<"修改value2后,value2="<<value2<<endl;//指针作为函数参数示例value1=10;value2=20;cout<<"\n调用modifyByPointer函数前,value1="<<value1<<endl;cout<<"调用modifyByPointer函数前,value2="<<value2<<endl;modifyByPointer(&value1);//通过指针传递cout<<"调用modifyByPointer函数后,value1="<<value1<<endl;cout<<"调用modifyByPointer函数后,value2="<<value2<<endl;return0;}//使用指针作为参数的函数voidmodifyByPointer(int*ptrValue){*ptrValue=200;//通过指针修改指向变量的值}初始时ptr指向value1,value1=10初始时ptr指向value1,value2=20修改value2后,value1=10修改value2后,value2=30

调用modifyByPointer函数前,value1=10调用modifyByPointer函数前,value2=20调用modifyByPointer函数后,value1=200调用modifyByPointer函数后,value2=20程序输出如下:26引用与指针的区别当函数参数为引用类型时,可直接操作实参。如下代码所示,modifyByReference函数通过引用传递变量value1,并在函数内部修改其值。voidmodifyByReference(int&refValue);intmain(){intvalue1=10;intvalue2=20;//指针示例int*ptr=&value1;cout<<"初始时ptr指向value1,value1="<<value1<<endl;cout<<"初始时ptr指向value1,value2="<<value2<<endl;ptr=&value2;//指针可以改变指向*ptr=30;//通过指针修改value2的值cout<<"修改value2后,value1="<<value1<<endl;cout<<"修改value2后,value2="<<value2<<endl;

//引用作为函数参数示例value1=10;value2=20;cout<<"\n调用modifyByReference函数前,value1="<<value1<<endl;cout<<"调用modifyByReference函数前,value2="<<value2<<endl;modifyByReference(value1);//通过引用传递cout<<"调用modifyByReference函数后,value1="<<value1<<endl;cout<<"调用modifyByReference函数后,value2="<<value2<<endl;return0;}//使用引用作为参数的函数voidmodifyByReference(int&refValue){refValue=100;//修改引用的值,实际上修改的是原变量的值}函数重载0427第1.4节28函数重载函数重载指同一函数名可对应多个不同的函数实现。此处的“不同”指这些函数或形参表存在差异:可能表现为形参数量不同,可能表现为形参类型不同,亦可能两者皆不相同。若非如此,则无法实现函数重载。例如:intfunc1(int);intfunc1(int,int);intfunc1(double,int);intfunc1(double,double,double);29函数重载重载函数的类型指其返回类型可以相同也可以相异。但若仅返回类型不同,而函数名称与形参表完全相同,则属于非法定义,编译器将报出语法错误。例如:在以上代码中,当调用重载函数func1()时,编译器需确定该函数名具体指向哪个函数。编译器根据实参的数量与类型,对所有名为func1的函数形参逐一进行比较,从而确定并调用最匹配的函数。intfunc1(inta,intb);doublefunc1(inta,intb);30函数重载例题:实现一个打印函数,该函数支持整型及字符串类型的输出。voidprint(inti){cout<<"printainteger:"<<i<<endl;}voidprint(stringstr){cout<<"printastring:"<<str<<endl;}printainteger:12printastring:helloworld!程序输出如下:intmain(){print(12);print("helloworld!");return0;}默认参数0531第1.5节32默认参数C++允许在函数定义过程中为一个或多个参数指定默认值。当调用该函数时,若提供了实际参数,则采用实际参数值;若未提供相应实参,则采用预设的默认值。函数默认参数仅能在函数申明中指定一次。该特性的优势在于,函数调用时可选择不提供或仅提供部分实际参数。

intadd(intx=5,inty=6){

returnx+y;}intmain(){inti;i=add(10,20);//10+20cout<<"i="<<i<<endl;i=add();//5+6cout<<"i="<<i<<endl;i=add(10);//10+6cout<<"i="<<i<<endl;}i=30i=11i=16程序输出如下:33默认参数函数定义中包含默认参数时,若调用时提供了所有参数,则采用传入的参数值;若调用时未提供某一参数,则采用该参数的默认值。例如:intadd(intx=5,inty=6){returnx+y;}intmain(){inti;i=add(10,20);//10+20cout<<"i="<<i<<endl;i=add();//5+6cout<<"i="<<i<<endl;i=add(10);//10+6cout<<"i="<<i<<endl;return0;}i=30i=11i=16程序输出如下:34默认参数在函数定义中包含默认参数时,可接受参数类型相异。例如:doubleadd(doublex=3.14,inty=10){returnx+y;}intmain(){doubleresult;result=add(2.718,5);//2.718+5cout<<"result="<<result<<endl;result=add(2.718);//2.718+10cout<<"result="<<result<<endl;return0;}程序输出如下:result=7.718result=12.71835默认参数函数申明时若包含默认参数,则函数定义中无需重复申明。例如:intsubtract(intx,inty=4);//函数申明,带有默认参数intsubtract(intx,inty){//函数定义,不用默认值returnx-y;}intmain(){inti;i=subtract(15,5);//15-5cout<<"i="<<i<<endl;i=subtract(15);//15-4(使用默认参数)cout<<"i="<<i<<endl;return0;}i=10i=11程序输出如下:36默认参数在C++语言中,占位符参数作为特殊语法要素,其作用在于确保函数申明与定义的参数列表一致性。该参数需在函数申明中体现,但在实际函数定义中无需使用。例如://函数申明,包含占位符参数voidfunc(intx,inty,int);intmain(){func(1,2,3);//调用函数return0;}//函数定义,不使用占位符参数voidfunc(intx,inty,int){cout<<"x+y="<<x+y<<endl;}程序输出如下:x+y=3for循环介绍0637第1.6节38传统for循环在C++语言中,for循环主要包含两种形式:其一为传统for循环,其二为C++11标准所引入的范围for循环(range-basedforloop)。传统for循环的语法结构:for(初始化表达式;条件表达式;操作表达式){//循环体}39传统for循环例如:

for(inti=0;i<100;i++)初始化表达式为inti=0,允许在for语句中定义局部变量,该表达式仅在循环起始时执行一次,用于初始化循环变量。条件表达式为i<100,在每次循环迭代前进行判断;若条件为真,则执行循环体;若条件为假,则退出循环。操作表达式为i++,在每次循环体执行完毕后执行,通常用于更新循环变量的值。40范围for循环范围for循环避免了传统for循环中手动管理索引或迭代器的繁琐性。由于无需直接操作索引或迭代器,该循环可减少因索引越界或迭代器失效而引发的错误。范围for循环的语法结构:“元素类型”指代容器中元素的类型,“变量名”用于存储每次迭代所获元素的临时变量,“容器”指待迭代的对象,可为数组、vector、list、set诸如此类的容器。for(元素类型

变量名:容器){//循环体}intarr[]={10,20,30,40,50};for(inti:arr){cout<<i<<"";}41范围for循环auto关键字在申明变量时能够使编译器自动推断其类型。例如:在以上代码中,范围for循环以auto关键字替代了类型申明。当运用C++标准库中的各类容器时,该循环结构能够高效遍历容器元素。如以下代码所示,范围for循环采用auto关键字遍历数组。autoa=10;//编译器推断a的类型为intautob=3.14;//编译器推断b的类型为doubleautoc="Hello";//编译器推断c的类型为constchar*autod='A';//编译器推断d的类型为charintarr[]={10,20,30,40,50};for(autoi:arr){cout<<i<<"";}数组表示方法0742第1.7节43string(字符串)类型简介string类型是C++标准库中定义的一种数据类型,用于表示可变长度的字符串。相较于C语言中采用字符数组表示字符串的方式,C++提供的string类型具备更高的易用性,且该类型与字符数组之间可实现相互转换。string类型定义于std命名空间中。在C++源文件中使用该类型前,通常需在文件起始位置添加#include<string>与usingnamespacestd;语句,以便后续直接使用string类型。若未添加这些语句,则每次使用均需显式指定为std::string。44string(字符串)类型定义与初始化定义与初始化string对象存在以下几种常用方式:strings1;该语句执行默认初始化,生成空字符串对象s1(不含任何字符)。strings2="IloveChina!";该语句将字符串字面量"IloveChina!"的内容复制至s2所管理的内存区域。strings3("IloveChina!");此初始化方式效果等同于s2,同样实现字符串内容至s3内存区域的复制。45string(字符串)类型定义与初始化strings4=s2;该语句将s2的内容完整复制至s4所管理的内存区域。strings5(6,'a');该语句初始化s5为由6个字符'a'构成的字符串。此方式在系统内部会生成临时对象,故不推荐采用。46string(字符串)类型操作string对象支持若干常用”操作”。例如:empty():判断是否为空,返回布尔值。例如:strings1;if(s1.empty()){//是否为空cout<<"s1为空"<<endl;}s1为空程序输出如下:47string(字符串)类型操作size()或length():返回字节或字符的数量,通常表示其返回值类型为无符号整型(unsignedint)。strings1;cout<<s1.size()<<endl;cout<<s1.length()<<endl;strings2="我爱中国";cout<<s2.size()<<endl;//一个汉字,2个字节cout<<s2.length()<<endl;0088程序输出如下:48string(字符串)类型操作s[n]:返回字符串s的第n个字符(n为整型值),字符位置索引从0起始,且索引值n必须小于size()。若下标引用超出该范围或对空字符串进行下标访问,将导致未定义行为。例如:strings3="Shanghai";if(s3.size()>4){cout<<s3[4]<<endl;s3[4]='w';//将索引为4的字符修改为'w'}cout<<s3<<endl;aShangwai程序输出如下:49string(字符串)类型操作s1+s2:字符串连接操作执行后,返回连接结果,从而生成一个新的字符串对象string。strings4="abcd";strings5="hijk";strings6=s4+s5;cout<<s6<<endl;abcdhijk程序输出如下:50string(字符串)类型操作compare():该方法通过比较字符串的ASCII码值返回整型结果。当执行pare(s2)时,若返回值为负整数,表示s1的字典序小于s2;若返回值为正整数,表示s1的字典序大于s2;若返回值为零,则表示两个字符串完全相等。例如:strings1="abc";strings2="abd";cout<<"Compares1ands2:"<<pare(s2)<<endl;

程序输出如下:Compares1ands2:-151string(字符串)类型操作insert():例如s3.insert(1,"123")在索引位置1插入字符串"123",原字符串变为"a123bc"。strings3="abc";s3.insert(1,"123");cout<<"Insertintos3:"<<s3<<endl;程序输出如下:Insertintos3:a123bc52string(字符串)类型操作append():例如s4.append("def")将字符串"def"追加到s4的末尾,结果为"abcdef"。strings4="abc";s4.append("def");cout<<"Appendtos4:"<<s4<<endl;Appendtos4:abcdef程序输出如下:53string(字符串)类型操作replace():例如s5.replace(1,2,"123")从索引位置1开始,替换2个字符为"123"。即使"123"的长度超过2,仍然会替换指定位置的2个字符,原字符串变为"a123de"。strings5="abcde";s5.replace(1,2,"123");cout<<"Replaceins5:"<<s5<<endl;Replaceins5:a123de程序输出如下:54string(字符串)类型操作tolower():使用基于范围的for循环遍历字符串中的每个字符,并将其转换为小写形式。使用tolower函数需引用<cctype>头文件。strings6="HELLO";for(char&c:s6){c=tolower(c);}cout<<"Converttolowercase:"<<s6<<endl;Converttolowercase:hello程序输出如下:55string(字符串)类型操作tolower():通过范围for循环遍历字符串中的每个字符,并将其转换为大写字母。使用toupper函数需引用<cctype>头文件。strings7="world";for(char&c:s7){c=toupper(c);}cout<<"Converttouppercase:"<<s7<<endl;Converttouppercase:WORLD程序输出如下:56string(字符串)类型支持多种操作符此外,string对象支持多种操作操作符,包括赋值和比较。s1=s2字符串对象赋值操作将使用s2的内容替换s1原有的内容。例如:strings7="abcd";strings8="de";s7=s8;cout<<s7<<endl;de程序输出如下:57string(字符串)类型支持多种操作符s1==s2确定两个字符串是否相等,需满足长度相同且所有字符完全一致;该比较具有大小写敏感性,即大写字母与小写字母被视为不同的字符。strings9="abc";strings10="abc";if(s9==s10){cout<<"s9==s10"<<endl;}s9==s10程序输出如下:58string(字符串)类型支持多种操作符s1!=s2判断两个字符串是否不相等。strings9="abc";strings10="abC";if(s9!=s10){cout<<"s9!=s10"<<endl;}s9!=s10程序输出如下:59string(字符串)类型支持多种操作符find()

用于在字符串中查找子字符串或字符的位置。程序输出如下:intmain(){strings1="Hello,world!";size_tfound=s1.find("world");if(found!=string::npos){cout<<"Substringposition:"<<found<<endl;}else{cout<<"Substringnotfound."<<endl;}found=s1.find('!');if(found!=string::npos){//string::npos是一个特殊的常量,表示“未找到”cout<<"Characterfoundatposition:"<<found<<endl;}else{cout<<"Characternotfound."<<endl;}return0;}Substringposition:7Characterfoundatposition:12程序输出如下:Const修饰0860第1.8节61常量指针常量指针指指针所指向的对象为常量,其特性表现为不可通过该指针修改指向对象的值,但允许指针本身指向其他对象,即指针的存储地址可变。语法定义如下:const关键字位于星号*左侧时,修饰指针所指向的对象,表示的是"指向常量的指针"。该指针的指向可变,但其所指向的值不可变:指针可重新指向不同变量,但不可通过解引用操作(*指针)修改所指向对象的值,即使被指对象本身并非常量。例如:const数据类型*指针名;inta=10,b=20;constint*p=&a;//常量指针,指向a//*p=30;//错误!不能通过常量指针修改值

p=&b;//正确,指针可重新指向bint*ptr=&a;//普通指针,可通过ptr修改a的值

*ptr=30;//正确,a的值变为30指针指向可以改,指针指向的值不可以更改62指针常量指针常量系指指针本身为常量,即其所存储的地址不可修改。如果指向的对象并非常量,则可通过该指针修改其指向对象的值。语法定义如下:const位于星号*右侧,表明指针本身为常量。该指针不可重定向但指向的值可变,须在初始化时指定地址,后续不可指向其他对象,然而可通过解引用修改所指向的值。指针常量必须在申明时赋值,否则将导致编译错误,因其后续不可再被赋值。例如:数据类型*const指针名=初始地址;

inta=10,b=20;int*constp=&a;//指针常量,初始化为a的地址

p=&b;//错误!指针地址不可修改

*p=30;//正确,修改a的值为30指针指向不可以改,指针指向的值可以更改63既修饰指针又修饰常量既修饰指针又修饰常量,即指针本身和所指向的对象均为常量,两者的值均不可修改。语法定义如下:const限定符分别出现在星号*两侧时,将同时修饰指针指向的对象与指针本身。此时,指针地址不可修改,且无法通过解引用操作修改所指向的值。必须在申明时指定初始地址,否则将无法通过编译。后续既无法修改指向关系,也不能修改所存储的数值。例如:const数据类型*const指针名=初始地址;

inta=10,b=20;constint*constp=&a;//指向常量的常量指针,初始化为a的地址

p=&b;//错误!指针地址不可修改

*p=30;//错误!不能通过指针修改值

int*ptr=&a;//普通指针,可通过ptr修改a的值(若a不是常量)

*ptr=30;//正确,a的值变为30(仅当a本身不是常量时)动态内存0964第1.9节65内存介绍在C++中,内存空间通常划分为若干功能各异的区域,主要包括栈、堆、全局/静态存储区、常量存储区及程序代码区。各区域均具备特定的用途与属性:栈(Stack):存储函数内部申明的局部变量,其内存空间由编译器自动分配与释放。堆(Heap):程序员可通过malloc或new操作符在此区域动态分配内存。使用完毕后,必须显式调用free()函数或delete操作符释放内存。若未能及时释放,将导致内存泄漏,严重时可致使程序崩溃。66内存介绍全局/静态存储区:用于存储全局变量及静态变量,此类内存在程序运行结束时被释放。常量存储区:专用于存储常量数据,其值不可变更,例如字符串字面量。程序代码区:存储程序的可执行机器指令,其功能对应于C语言中的程序代码区。栈区:空间容量受系统严格约束。栈内存的分配与释放机制高效,但开发者无法干预其管理过程。堆区:开发者可自主决定内存分配规模,理论上仅受物理内存总量限制。相较于栈操作,堆内存分配效率较低,但具备高度灵活性。内存需通过new或malloc操作符显式申请,并通过free或delete操作符显式释放。67malloc和free在C语言中,malloc与free是标准库提供的函数,用于从堆空间动态分配与释放内存。malloc的全称为memoryallocation,意为动态内存分配,该函数的一般形式为:当不再使用该内存时,应使用free()函数释放该内存,该函数的一般形式为:void*malloc(intNumBytes);voidfree(void*Ptr);68malloc和freeint*p=NULL;p=(int*)malloc(10*sizeof(int));//分配了40字节if(p!=NULL){*p=5;//相当于p[0],存5这个数*(p+1)=6;//相当于p[1],存6这个数cout<<*p<<endl;cout<<*p<<endl;free(p);//千万不要忘记,否则就是内存泄漏。如果泄漏多了,程序就会崩溃}在以下代码中,通过malloc函数分配内存,继而检查分配是否成功,即指针是否非空。若分配成功,即可使用该内存区域。使用完毕后,务必调用free函数释放内存,以防止内存泄漏。69malloc和freechar*point=NULL;point=(char*)malloc(100*sizeof(char));//100个位置if(point!=NULL){strcpy_s(point,20,"helloworld!");//使用安全版本的strcpycout<<point<<endl;free(point);}在以上代码中,采用了strcpy_s函数,该函数为更安全的字符串复制函数。其允许显式指定目标缓冲区的大小,从而避免缓冲区溢出。70new和delete在C++中,new与delete是用于动态内存分配与释放的关键字。相较于C语言中的malloc与free,二者提供了更为类型安全且灵活的内存管理方式。new操作符用于在堆区分配一段连续的内存空间。若分配成功,则返回指向该内存的指针;若分配失败,则返回NULL。此内存分配过程通常称为创建对象实例。与malloc()相比:在C++语言中,new作为关键字使用,无需包含相应的头文件。new操作符分配动态内存时会自动调用对象的构造函数。new操作符可依据初始化列表提供的值完成对象初始化。71new和delete下面介绍new操作符常见的几种用法:动态分配单个对象的内存,内存中的值是未初始化的,即随机值。如下代码所示,使用new分配单个对象并初始化为默认值。数据类型*指针变量=new数据类型;//默认值为随机值intmain(){int*ptr=newint();//分配一个int对象,初始化为0cout<<"Defaultvalue:"<<*ptr<<endl;deleteptr;//释放内存return0;}Defaultvalue:0程序输出如下:72new和delete在动态分配内存时对该对象进行初始化,其初始值即为内存分配时所赋予的数值。数据类型*指针变量=new数据类型(初始值);intmain(){int*ptr=newint(10);//分配一个int对象,初始化为10cout<<"Initializedvalue:"<<*ptr<<endl;deleteptr;//释放数组return0;}Initializedvalue:10程序输出如下:73new和delete动态分配数组所需内存空间,并返回指向该数组首元素的指针。其内部各元素均处于未初始化状态,故取值未定义。数据类型*指针变量=new数据类型[数组长度];

intmain(){int*arr=newint[5];//创建一个包含5个int的数组for(inti=0;i<5;++i){arr[i]=i*i;//初始化数组元素}for(inti=0;i<5;++i){cout<<"Element"<<i<<":"<<arr[i]<<endl;}delete[]arr;//释放数组return0;}Element0:0Element1:1Element2:4Element3:9Element4:16程序输出如下:74new和delete动态分配数组内存,并通过初始化列表为数组元素赋初值;初始化列表中的数值依序赋予数组各元素。intmain(){int*arr=newint[3]{1,2,3};//创建并初始化一个包含3个int的数组for(inti=0;i<3;++i){cout<<"Element"<<i<<":"<<arr[i]<<endl;}delete[]arr;//释放内存return0;}Element0:1Element1:2Element2:3程序输出如下:数据类型*指针变量=new数据类型[数组长度]{初始化列表};75new和deletedelete操作符用于释放由new操作符所分配的内存。每个new操作应当对应一个delete操作,执行delete操作将释放相应的内存。语法定义如下:delete指针名;//释放单个对象delete[]指针名;//释放数组intmain(){//动态分配一个string对象string*pStr=newstring("Hello,C++!");//使用并释放该string对象cout<<"Dynamicstring:"<<*pStr<<endl;deletepStr;return0;}Dynamicstring:Hello,C++!程序输出如下:76new和delete在使用new[]操作符进行动态数组分配时,必须采用delete[]操作符进行内存释放。原因在于new[]操作会分配额外内存以存储数组长度信息,而delete[]能够依据该信息完整释放所有数组元素所占用的内存空间。例如:intmain(){//动态分配一个string数组string*pStrArray=newstring[5];for(inti=0;i<5;i++){pStrArray[i]="Element"+to_string(i);}//使用并释放string数组for(inti=0;i<5;i++){cout<<pStrArray[i]<<endl;}delete[]pStrArray;//正确释放数组return0;}程序输出如下:Element0Element1Element2Element3Element4本章小结1077第1.10节78本章小结

阐述了C++语言的输入输出机制、字符串与字符处理、布尔类型、引用操作相关知识。介绍了C++函数重载、默认参数、循环结构、数组等核心内容。讲解了C++动态内存管理部分new与delete操作符的使用方法及其关键作用。结束大学计算机基础教学系列教材第二章面向对象概念——封装与继承2026年5月11日目录封装第2.1节构造和析构第2.2节继承第2.3节本章小结第2.4节01020304CONTENTS学习目标

理解类、对象、封装、继承与多态的概念及其应用。

掌握类的定义、对象的创建,以及封装、继承、多态相关语法和用法,能够综合运用这些特性实现复杂的业务逻辑。

学会合理利用封装、继承与多态来设计和优化代码,以提升程序的可维护性、可扩展性和可读性。封装01第2.1节类和对象类与对象是面向对象编程中的基本构成要素。类(Class)通过对现实世界实体的抽象化过程,将该类别的属性(数据)与行为(操作)封装为一个逻辑单元。而对象则是类的具体实例,每个对象均继承类中定义的属性与行为,并可具备各自的特定状态。

一组具有相同属性和行为的对象可抽象为一个类。

为便于理解,可将属性定义为对象的数据成员(常量或变量),而将行为对应为可对对象执行的操作(即函数或方法)。类和对象C++语言引入了class语法特性,定义类的基本语法如下:采用关键字class可定义一个类,该类可包含成员属性与成员函数,分别对应于前述语法中的属性与行为。如下代码所示,定义了一个名为Person的抽象类:class类名{访问权限:属性;行为;};classPerson{public://成员属性stringname;intage;voidintroduce(){//成员函数cout<<"Mynameis"<<name<<".Iam"<<age<<"yearsold."<<endl;}};创建类对象的方式

对象是类的实例化。创建类的对象存在以下几种常见方式:直接申明对象类名

对象名//实例化一个对象对象名.属性//使用对象的属性对象名.函数//使用对象的函数在主函数或其他函数中,可如同申明普通变量一般直接申明类的对象,其定义与使用方法如下:创建类对象的方式

如下代码所示,创建Person类的一个实例对象p,并调用该对象p的属性与方法:intmain(){Personp;="Alice";p.age=30;roduce();return0;}MynameisAlice.Iam30yearsold.程序输出如下:创建类对象的方式通过new运算符动态创建对象intmain(){Person*p=newPerson();//使用new关键字动态分配内存创建Person对象p->name="Bob";//通过指针p使用->运算符符来访问对象的成员p->age=25;p->introduce();deletep;//释放动态分配的内存Personp1;="alice";p1.age=21;p=&p1;//指针p指向实例对象p1的地址

p->introduce();return0;}MynameisBob.Iam25yearsold.Mynameisalice.Iam21yearsold.程序输出如下:

使用new运算符可在程序运行时动态创建对象,以实现运行时的动态内存分配。当指针指向由new创建的对象时,需使用"->"运算符访问该对象的成员属性及成员函数。

创建类对象的方式使用对象数组在需要创建同一类的多个对象时,可考虑采用对象数组。此方式尤为适宜对同类型数据进行批量管理。intmain(){Personpeople[3];people[0].name="Charlie";people[0].age=35;people[1].name="David";people[1].age=40;people[2].name="Eve";people[2].age=28;

MynameisCharlie.Iam35yearsold.MynameisDavid.Iam40yearsold.MynameisEve.Iam28yearsold.程序输出如下:for(inti=0;i<3;i++){people[i].introduce();}return0;}封装

封装是面向对象编程的另一项基本概念,意为将数据(属性)与相关操作(行为)整合于类中,并隐藏具体内部实现细节,仅对外提供必要的访问接口。该机制实现了信息隐藏与接口隔离,能够有效降低代码耦合度,提升系统的可维护性、可扩展性及安全性保障。封装特点数据隐藏:封装机制通过将类的属性设置为私有(private)或保护(protected),实现数据隐藏。外部代码不能直接访问或修改这些数据成员,从而确保数据安全性与完整性。如下代码所示,类外部无法访问私有属性age。classPerson{public:stringname;private: intage;};intmain(){Personp;="Alice";p.age=30;//报错,类外无法访问私有属性return0;}封装特点公共接口:通过公开公共(public)函数作为访问私有数据的接口,外部代码仅能通过这些方法与对象交互,从而实现对数据访问的严格控制。如下列代码所示,第11行定义的公有函数setAge,使外部代码可通过该函数访问私有属性age。classPerson{public:stringname;voidintroduce(){cout<<"Mynameis"<<name<<"Iam"<<age<<"yearsold."<<endl;}voidsetAge(intAge){ //对私有属性赋值

age=Age; }private: intage;};intmain(){Personp;="Alice";p.setAge(30); //调用公有函数访问私有属性

roduce();return0;}封装特点提高可维护性:通过封装内部实现细节,可以在不改变类的外部接口的前提下,自由调整和优化其内部结构,从而显著提升代码的可维护性。当修改Person类中的setAge方法时,只要其调用接口保持不变,就不会影响外部使用。classPerson{public:stringname; voidsetAge(intAge){//更改代码,无需通知主函数 if(Age>0){ age=Age; }}voidintroduce(){cout<<"Mynameis"<<name<<"Iam"<<age<<"yearsold."<<endl;}private: intage;};封装特点简化复杂性:封装将复杂的内部逻辑隐藏在类内部,用户仅需关注所提供的公共接口,无需了解其底层实现细节,从而降低了使用和理解的难度。

增强代码的可读性:通过将相关的属性和行为组织在同一类中,使结构清晰且职责明确,从而使代码更易于阅读和理解。成员属性和函数类的成员属性构成对象状态的核心组成部分。通过合理的访问控制设置,可有效管理对象状态,实现数据的封装与安全保护。合理设计类的成员属性至关重要,它不仅决定了对象行为的正确性与一致性,还直接影响到程序的可维护性、扩展性以及整体架构的稳定性。定义成员属性的方式兼具直观性与简洁性。如下代码所示,定义用于表示二维平面上点的类Point:classPoint{public:intx;//成员属性,用于存储点的x坐标inty;//成员属性,用于存储点的y坐标};成员属性和函数访问修饰符对成员属性的控制C++提供三种访问修饰符:public(公共)、private(私有)与protected(受保护)。这些修饰符对成员属性的访问权限实施严格限定,有效增强了数据安全性。public成员属性在类的内部及外部均可被无限制地访问与修改。

classPoint{public:intx;inty;};intmain(){Pointp;//创建Point类的对象pp.x=3;//在类外部直接访问并修改public成员属性xp.y=5;//同理cout<<"Pointp:("<<p.x<<","<<p.y<<")"<<endl;return0;}Pointp:(3,5)程序输出如下:成员属性和函数private成员属性仅可在类的内部访问与修改,类外部无法直接访问。如下代码所示,将Point类的成员属性声明为private,将数据的访问与修改操作封装于类的内部,仅能通过公有成员函数提供有限且可控的访问接口。classPoint{private:intx;inty;public:voidsetX(intnewX){x=newX;}//提供公共的成员函数来设置x的值voidsetY(intnewY){y=newY;}//提供公共的成员函数来设置y的值intgetX()const{returnx;}

//提供公共的成员函数来获取x的值

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论