c++ 重点
- 格式:doc
- 大小:90.00 KB
- 文档页数:6
大一下学期C语言期末重点知识点总结在大一下学期的C语言课程中,我们学习了很多基础的编程概念和技能。
在期末考试前,我们需要对学过的知识做一个全面的复习和总结,以便更好地准备考试。
以下是我根据学习笔记和教材整理的大一下学期C语言期末重点知识点:1. 指针指针是C语言中最重要的概念之一,理解指针的意义和使用方法对于提高程序员的编程能力至关重要。
指针有如下使用方法:1. 定义指针变量:定义指针变量需要指定一个指针类型,例如int*。
在定义后,我们可以将其赋值为一个地址。
2. 操作指针变量:操作指针变量时,我们可以使用两个运算符:*和&。
*运算符表示取出指针指向地址中的值,而&运算符表示获取地址。
3. 指针作为函数参数:函数可以定义一个参数作为指针类型,然后使用指针来传递变量的地址,以便在函数中对其进行修改。
4. 动态分配内存:使用malloc函数可以动态分配内存,返回指向所分配内存的指针。
动态分配内存的好处是我们可以在运行时根据需要动态地按照需要分配内存。
2. 结构体结构体是C语言中另一个重要的概念。
它允许我们定义一个包含多个成员(变量)的类型。
每个成员可以是不同的类型。
我们可以按照如下方式定义结构体:1. 关键字struct:使用关键字struct来定义结构体类型。
例如,我们可以定义一个名为student的结构体类型,它包含名字和年龄两个成员。
2. 内部成员:我们可以在结构体内部定义成员变量。
成员变量的类型可以是任何C语言类型。
3. 访问结构体成员:我们可以通过相应的结构体变量和“.”运算符来访问结构体成员。
4. 结构体指针:我们也可以定义指向结构体的指针,类似于定义指针变量。
使用->运算符来访问结构体指针所指向的成员。
3. 数组数组是C语言中最常见的数据类型之一。
数组是一种容器,可以存储一组有序的数据。
以下是常见的数组操作方法:1. 定义数组变量:定义数组变量时需要指定一个类型和用于存储数据的空间大小。
1 设x 为int 型变量,请写出描述“x 是偶数”的表达式是_x%2==0_确定且有限的步骤_。
2 已知scanf("a=%d,b=%d,c=%d"&a,&b,&c);,若从键盘输入2、3、4 三个数分别作为变量a、b、c 的值则正确的输入形式是_a=2,b=3,c=4_a=2,b=3,c=4_。
3 设有语句int a=3;,则执行了语句a+=a-=a*a 后,变量a 的值是_-12__。
4 以下程序的输出结果是_10。
main() { int a=-10,b=-3; printf("%d\u005cn"-a++); printf("%d\u005cn"-a+b); }5 以下程序的输出结果是-14。
main() { char c;6以下程序段(n所赋的是八进制数)执行后输出结果是32767.32767。
9字符串\\name\\\101ddress\b\xaf的长度为:15。
二填空题(每题3 分,共30 分)1 以下程序运行后的输出结果是9.10。
#include main() { int i=010 , j=10; printf("%d,%d\u005cn"++i,j--); }2 以下程序运行后的输出结果是000。
#include main() { printf("%d%d%d\u005cn"'\0','\0','\0'); }3 以下程序运行后的输出结果是i=11,j=15,k=33。
main() { int i=5,j,k; j=i+++i+++i++; k=(++i)+(++i)+(++i); printf("i=%5d j=%5d\u005cnk=%5d\u005cn"i,j,k); }4 下面的程序运行时从键盘上输入9876543210<回车>,程序的输出结果是a=98。
c语言重点笔记C语言重点笔记一、基础语法1.注释:用于解释代码,不会被编译器执行。
单行注释以“//”开头,多行注释用“/* */”包围。
2.变量:用于存储数据。
定义变量时需要指定类型和名称,如int num;赋值时使用等号,如num=10;也可以在定义时进行赋值,如int num=10;3.数据类型:C语言提供了基本的数据类型,包括整型、浮点型、字符型等。
4.运算符:C语言提供了各种运算符,包括算术运算符、关系运算符、逻辑运算符等。
5.控制语句:C语言提供了各种控制语句,包括条件语句、循环语句等。
二、函数1.函数定义:函数是一段可重复使用的代码块。
定义函数需要指定返回值类型、函数名和参数列表。
如int add(int a, int b) { return a + b; }2.函数调用:调用函数时需要使用函数名和参数列表,并根据返回值类型进行接收。
如int result = add(1, 2);3.递归函数:递归是一种特殊的函数调用方式,在函数内部调用自身。
需要注意避免死循环。
三、数组1.数组定义:数组是一组相同类型的数据。
定义数组时需要指定类型和长度,如int arr[5];2.数组初始化:可以在定义时进行初始化,如int arr[5] = {1, 2, 3, 4, 5};3.数组访问:使用下标访问数组元素,下标从0开始,如arr[0]表示数组的第一个元素。
4.多维数组:多维数组是由一维数组组成的。
二维数组可以看作是一个矩阵,定义时需要指定行数和列数。
四、指针1.指针定义:指针是一个变量,用于存储另一个变量的地址。
定义指针时需要指定类型和名称,如int *p;2.指针运算:可以对指针进行加减运算,表示移动指针位置。
3.指针与数组:可以使用指针访问数组元素,如int *p = arr; p[0]表示arr[0]。
4.空指针:空指针是没有被初始化的指针。
五、结构体1.结构体定义:结构体是一种自定义数据类型,可以包含多个不同类型的成员变量。
C语⾔重点[1][2]1.设有定义:int n=0,*p=&n,**q=&p,则下列选项中正确的赋值语句是(A)A、*p=5;B、*q=2;C、p=1;D、q=p;2. C语⾔中函数调⽤的⽅式有(C)。
A、函数调⽤作为语句或函数表达式两种B、函数调⽤作为语句⼀种C、函数调⽤作为语句、函数表达式或函数参数三种D、函数调⽤作为函数表达式⼀种3. 已知函数的调⽤形式:fread(buffer,size,count,fp);其中buffer代表(D)。
A、⼀个⽂件指针,指向要读的⽂件B、⼀个存储区,存放要读的数据项C、⼀个整数,代表要读⼊的数据项总数D、⼀个指针,指向要读⼊数据的存放地址4. 以下程序段的输出是(C)int x = 496;printf(“*%-06d*\n”, x);A、*000496*B、* 496*C、*496 *D、输出格式不合法5. ⼀个C语⾔程序是由(C)。
A、⼀个主程序和若⼲⼦程序组成B、若⼲⼦程序组成C、函数组成D、若⼲过程组成6. 下列四组选项中,均不是C语⾔关键字的选项是(A)。
A、define IF typeB、include scanf caseC、while go powD、getc char printf7. 若有说明:int n=2,*p=&n,*q=p;,则以下⾮法的赋值语句是(C)。
A、n=*q;B、p=q;C、p=n;D、*p=*q;8. 以下程序的输出结果是Bvoid prtv(int *x){ printf(“%d\n”, ++*x); }main(){ int a = 25;prtv(&a);}A、24B、26C、23D、259. ⼀个算法应该具有“确定性”等5个特性,下⾯对另外4个特性描述错误是(B)。
A、有穷性B、有零个或多个输出C、可⾏性D、有零个或多个输⼊10. 以下叙述中正确的是(A)。
A、宏替换不占⽤运⾏时间,只占编译时间B、在以下定义中 C R 是称为"宏名"的标识符 #define C R 045C、在程序的⼀⾏上可以出现多个有效的预处理命令⾏D、使⽤带参的宏时,参数的类型应与宏定义时的⼀致11. fgetc函数的作⽤是从指定⽂件读⼊⼀个字符,该⽂件打开⽅式必须是(D)。
C语言最重要的知识点总体上必须清楚的:1)程序结构是三种: 顺序结构、选择结构(分支结构)、循环结构。
2)读程序都要从main()入口, 然后从最上面顺序往下读(碰到循环做循环,碰到选择做选择),有且只有一个main函数。
3)计算机的数据在电脑中保存是以二进制的形式. 数据存放的位置就是他的地址.4)bit是位是指为0 或者1。
byte 是指字节, 一个字节 = 八个位.概念常考到的:1、编译预处理不是C语言的一部分,不占运行时间,不要加分号。
C 语言编译的程序称为源程序,它以ASCII数值存放在文本文件中。
误的,一定不能出现分号。
3、每个C语言程序中main函数是有且只有一个。
4、在函数中不可以再定义函数。
5、算法:可以没有输入,但是一定要有输出。
第一章 C语言的基础知识第一节、对C语言的基础认识1、C语言编写的程序称为源程序,又称为编译单位。
2、C语言书写格式是自由的,每行可以写多个语句,可以写多行。
3、一个C语言程序有且只有一个main函数,是程序运行的起点。
第二节、2、每个C语言程序写完后,都是先编译,后链接,最后运行。
(.c---(.obj---(.exe)这个过程中注意.c和.obj文件时无法运行的,只有.exe文件才可以运行。
(常考!)(程序编辑-程序编译-程序连接-程序运行)第三节、标识符1、标识符(必考内容):合法的要求是由字母,数字,下划线组成。
有其它元素就错了。
并且第一个必须为字母或则是下划线。
第一个为数字就错了预定义标识符:背诵define scanf printf 2 include。
记住预定义标识符可以做为用户标识符。
第五节:整数与实数1)C语言只有八、十、十六进制,没有二进制。
但是运行时候,所有的进制都要转换成二进制来进行处理。
(考过两次)a、C语言中的八进制规定要以0开头。
(数码取值0-7)018的数值是非法的,八进制是没有8的,逢8进1。
b、C语言中的十六进制规定要以0x(X)开头。
1.找出二维数组中最大的数.00000int fun (int a[][M])000000{000000int i,j,max=a[0][0];000000for(i=0;i<2;i++)000000for(j=0;j<M;j++)000000if(max<a[i][j]) 00000max=a[i][j];000000return max;00000}0000002. 求出迭代法中的和,精度为epd。
000000double s=1.0,s1=1.0;000000. int n=1;000000while(s1>=eps) /*当某项大于精度要求时,继续求下一项*/000000{s1=s1*n/(2*n+1); /*求多项式的每一项*/000000s=s+s1; /*求和*/00000n++;000000}000000return 2*s;0000003.求出能被整除的个数000000void fun (int *a, int *n)000000{000000int i,j=0;000000for(i=1;i<=1000;i++) /*求1到1000之内能被7或11整除、但不能同时被7和11整除的所有整数,并放入数组a中*/000000if((i%7==0||i%11==0)&&i%77!=0) 00000a[j++]=i;000000*n=j; 00000}0000004.求出字符串中只有字母的字符00000void fun( char *a )000000{000000int i,j=0;000000for(i=0;a[i]!='\0';i++)000000if(a[i]!='*') 000000a[j++]=a[i]; /*若不是要删除的字符'*'则留下*/000000a[j]='\0';000000}0000005.实现两个字符串的连接000000void fun(char p1[], char p2[])000000{int i,j;000000for(i=0;p1[i]!='\0';i++) ; 000000for(j=0;p2[j]!='\0';j++)000000p1[i++]=p2[j];00000p1[i]='\0';00000}0000006.某学生的记录由学号、8门课程成绩和平均分组成,学号和8门课程的成绩已在主函数中给出,请编写函数fun,其功能是:求出该学生的平均分,并放入记录的ave成员中。
3.6#include<stdio.h>void main(){charc1='a',c2='b',c3='c',c4='\10 1',c5='\116';printf("a%cb%c\tc%c\tabc\n",c1,c2,c3 );printf("\t\b%c%c\n",c4,c5) ;}结果aa bb cc abcAN3.8#include<stdio.h>void main(){int c1,c2;c1=97;c2=98;printf("%c%c\n",c1,c2); printf("%d%d\n",c1,c2); }结果a b97 983,9 #include<stdio.h>viod main(){int i,j,m,n;i=8;j=10;m=++i;n=j++;printf("%d,%d,%d,%d\n",i ,j,m,n);}9,11,9,10【例4.10】输入三角形的三边长,求三角形面积。
为简单起见,设输入的三个边长a,b,c能构成三角形。
从数学知识已知求三角形面积的公式为已知三角形的三边长a,b,c,则该三角形的面积公式为:))()((csbsassarea---=,其中s = (a+b+c)/2,据此编写程序如下:#include<stdio.h>#include<math.h>main(){float a,b,c,s,area;scanf(“%f,%f,%f”,&a,&b,&c);s=1.0/2*(a+b+c);area=sqrt(s*(s-a)*(s-b)*(s-c));printf(“a=%7.2f,b=%7.2f,c=%7.2f,s=%7.2f\n”,a,b,c,s);printf(“area=%7.2f\n”,area);}程序第8行中sqrt函数是球平方根的函数。
《C语言编程基础》电子教案第一章:C语言概述1.1 C语言的历史与发展1.2 C语言的特点1.3 C语言的应用领域1.4 开发环境搭建第二章:C语言基础语法2.1 数据类型2.1.1 整型2.1.2 浮点型2.1.3 字符型2.2 变量与常量2.2.1 变量的声明与初始化2.2.2 常量的定义2.3 运算符与表达式2.3.1 算数运算符2.3.2 关系运算符2.3.3 逻辑运算符2.3.4 赋值运算符2.3.5 其他运算符2.4 输入输出函数2.4.1 标准输入输出函数2.4.2 格式化输入输出函数第三章:控制语句3.1 顺序结构3.2 选择结构3.2.1 if语句3.2.2 switch语句3.3 循环结构3.3.1 while循环3.3.2 do-while循环3.3.3 for循环3.3.4 循环控制语句第四章:函数与指针4.1 函数的定义与调用4.1.1 函数的声明与定义4.1.2 函数的参数传递4.1.3 函数的返回值4.2 指针的基本概念4.2.1 指针的声明与赋值4.2.2 指针与数组4.2.3 指针与函数4.2.4 指针与动态内存分配第五章:数组与字符串5.1 一维数组5.1.1 数组的声明与初始化5.1.2 数组的访问与遍历5.2 二维数组5.2.1 二维数组的声明与初始化5.2.2 二维数组的访问与遍历5.3 字符串的基本操作5.3.1 字符串的声明与初始化5.3.2 字符串的长度计算5.3.3 字符串的复制与连接5.3.4 字符串的比较与搜索第六章:结构体与联合体6.1 结构体的定义与使用6.1.1 结构体的声明6.1.2 结构体的初始化6.1.3 结构体数组6.1.4 结构体指针6.2 联合体的定义与使用6.2.1 联合体的声明6.2.2 联合体的初始化6.2.3 联合体成员的访问6.3 枚举类型6.3.1 枚举类型的声明6.3.2 枚举类型的使用第七章:文件操作7.1 文件概述7.1.1 文件的概念7.1.2 文件类型7.1.3 文件操作函数7.2 文件的打开与关闭7.2.1 文件的打开7.2.2 文件的关闭7.3 文件的读写操作7.3.1 文件的读取7.3.2 文件的写入7.4 文件的定位与查找7.4.1 文件的定位7.4.2 文件的查找第八章:指针高级应用8.1 指针数组8.1.1 指针数组的声明8.1.2 指针数组的应用8.2 数组指针8.2.1 数组指针的声明8.2.2 数组指针的应用8.3 函数指针8.3.1 函数指针的声明8.3.2 函数指针的应用8.4 指针与动态内存分配8.4.1 动态内存分配的概念8.4.2 动态内存分配的函数8.4.3 动态内存分配的应用第九章:预处理指令9.1 预处理概述9.1.1 预处理的概念9.1.2 预处理的作用9.2 预处理指令9.2.1 文件包含指令9.2.2 宏定义指令9.2.3 条件编译指令9.3 预处理器的使用9.3.1 预处理器的工作流程9.3.2 预处理器的高级应用第十章:C语言编程实例10.1 实例一:计算器程序10.1.1 功能需求10.1.2 程序设计10.1.3 程序调试与测试10.2 实例二:图书管理系统10.2.1 功能需求10.2.2 程序设计10.2.3 程序调试与测试10.3 实例三:简单的游戏程序10.3.1 功能需求10.3.2 程序设计10.3.3 程序调试与测试重点和难点解析重点一:C语言的特点和应用领域解析:C语言作为一种高级编程语言,具有高效、灵活、可移植性好等特点。
c语言重点知识点总结c语言重点知识点总结上学的时候,说起知识点,应该没有人不熟悉吧?知识点是指某个模块知识的重点、核心内容、关键部分。
还在苦恼没有知识点总结吗?下面是小编帮大家整理的c语言重点知识点总结,欢迎大家分享。
c语言重点知识点总结篇1◆知识点1:交换两个变量值的方法1)采用第三方变量(最容易想到的方法)2)采用加减法进行值得交换(面试时常用**)代码如下:b = a - b;a = a - b;b = a + b;3)采用按位异或的位方式代码如下:a = a^b;b = a^b;a = a^b;◆知识点2:取语言重点知识点总结余运算%的结果与被除的符号相同,结果为两个正数取余后前面加符号◆知识点3:sizeof的使用sizeof是一种运算符不要想当然理解为函数sizeof使用时可以不加()sizeof可以加变量、常量、数据类型跟数据类型是必须加()◆知识点4:static和 extern区别是能否进行跨文件访问①函数②变量1、对函数的作用:外部函数:定义的函数能被本文件和其他文件访问内部函数:定义的函数只能被本文件访问默认情况下,所有函数都是外部函数(相当于带关键字extern),所以可以省略extern作用:完整的定义和引用一个外部函数都加extern引用时也是默认是外部函数所以也省略externstatic作用:定义一个内部函数使用:static返回类型函数名(参数列表)不能被其他文件调用一个项目中,本文件的外部函数名不能和其他文件的外部函数同名(error)本文件中的内部函数(static)可以和其他文件的函数名同名的2、对变量的作用:全局变量分为两种:外部变量:定义的变量可以被其他文件访问①默认情况下所有的全局变量都是外部变量②不同文件中的同名外部变量都代表同一个③定义一个外部变量不加extern,声明才加extern同样的声明是没有错误的内部变量:定义的变量不能被其他文件访问不同文件的同名内部变量互不影响◆知识点5:数组的几种初始化方式如下:int a[3] = {10, 9, 6};int a[3] = {10,9};int a[] = {11, 7, 6};int a[4] = {[1]=11,[0] = 7};(知道有此种初始化方式即可)◆知识点6:数组的内存分析和注意点存储空间的划分(内存的分配是从高地址到低地址进行的,但一个数组内部元素又是从低到高进行的)【注:对于以后学习重要】数组名的作用,查看元素地址注意数组不要越界◆知识点7:字符串知识点"123”其实是由’1’、’2’、’3’、’’组成字符串的输出”%s”,’’是不会输出的◆知识点8 :字符串处理函数:strlen()计算的是字符数,不是字数计算的字符不包括’’,一个汉字相当于3个字符例子:"哈haha" 字符数为7从某个地址开始的数字符个数,知道遇到’’为止指针部分在C语言中占据重要地位,所以重点学习与整理了指针的知识:◆知识点9:指针定义的格式变量类型 *变量名如:Int *p◆知识点10:指针作用能够根据一个地址值,访问对应的.存储空间例:Int *p;Int a = 90;P = &a;*p = 10;//把10赋值给p所指的存储空间◆知识点11:指针使用注意Int *p只能指向int类型的数据指针变量只能存储地址指针变量未经初始化不要拿来间接访问其他存储空间◆知识点12:指针与数组遍历数组int ages[5] = {10, 4, 9, 44, 99};for(int i = 0; i<5; i++){printf("%d ", ages[i]);}使用指针遍历数组:int *p;// 指针变量P指向了数组的首地址p = &ages[0];// 使用指针遍历数组for(int i = 0; i<5; I++){printf("ages[%d] = %d ", i, *(p + i));}注:指针+ 1取决于指针的类型注:数组的访问方式数组名[下标]指针变量名[下标]*(p + i)◆知识点12:指针与字符串定义字符串的两种方式:1、利用数组Char name[] = “Andyzhao”特点:字符串里的字符可以修改适用场合:字符串内容需要经常修改2、利用指针Char *name = “itcast”特点:字符串是一个常量,字符串里面的字符不能修改使用场合:字符串的内容不需要修改,而这个字符串经常使用◆知识点13:预处理指令(三种):宏定义条件编译文件包含1、宏定义的配对使用和带参数的宏:#define#undef带参数的宏:#define sum(v1,v2) ((v1) + (v2))//括号是必须的例如:#define pingfang(a) a*a#define pingfang(a) (a*a)调用时pingfang(10)/pingfang(2)//不正确pingfang(5+5)//不正确带参数的宏效率比函数高2、条件编译(一般是判断宏的值)#if 条件#elif 条件#else#endif(非常重要)不然后面的代码全部无效3、文件包含:<>表示系统自带的文件,""表示自定义文件不允许循环包含,比如ah包含bh,bh又包含ah◆知识点14:typedef 只是给类型起了个别名并不是定义新类型struct Student{int age;char *name;};typedef struct Student Student;等价于typedef struct Student{int age;char *name;}Student;也等价于typedef struct {int age;char *name;}Student;类似的给枚举类型起名typedef enum Sex{Man,Women}Sex;下面这种情况的写法比较特殊//下面是函数指针类型的自定义数据类型,返回值类型和参数类型要匹配#includetypedef int (*TypeFuncPointer)(int, int);int add(int a, intb){return a + b;}int minus(int a, intb){return a - b;}int main(){TypeFuncPointer p = add;//使用自定义类型TypeFuncPointer p2 = minus;//使用自定义类型printf("add = %d ",p(1, 2));printf("minus = %d ",p2(1, 2)); return 0;}下面是定义结构体的指针类型typedef struct Student{int age;char *name;}*PtrStu;//使用方式Student stu ={18, "zhangsan"}; PtrStu p = &stu;宏定义也是可以为类型起名的#define Integer int相当于typedef int Integer注意和typedef的区别例如:typedef char * String#define String2char *。
§继承继承(inheritance):一个新类从已有类那里获得其已有特性,称为继承。
派生(derivation):在已有类的基础上新增自己的特性而产生新类的过程称为派生。
为什么需要继承和派生?如果能在已有的资源基础上设计新类,则能加快编程速度;为什么要继承?新的问题与已解决过的问题有相似性。
为什么要派生改造?新的问题与已解决过的问题又有差异多态(polymorphism,源于希腊语,含义为“许多形式”)即在运行时确定调用哪个函数的能力。
基类和派生类若一个类C2从另一个类C1扩展而来,则称C2为派生类(derived class),C1为基类(base class)。
基类也称为父类(parent class), 派生类也称为扩展类(extended class)或子类(child class)。
一个派生类继承了其基类的所有数据成员和成员函数(除构造函数和析构函数外),还可以增加新的数据成员和函数,从而使派生类更具特殊化。
§1 派生类的定义单继承◆必须在类定义的头部指明它的基类:class 派生类名:继承方式基类名{派生类新增成员声明;};◆冒号“ :”表示继承。
◆继承方式指定了派生类从基类继承来的成员的访问权限。
☐public:公有继承☐protected:保护继承☐private:私有继承,默认为私有继承。
◆派生类成员包括从基类继承来的成员和新增加的成员。
多继承class 派生类名:继承方式基类名1,继承方式基类名2…{派生类新增成员声明;};§2派生类成员的构成及访问权限◆派生类中的成员包括☐从基类继承的成员(除构造函数和析构函数外,全部接收)☐新增加的成员(定义派生类自己的构造函数和析构函数)◆调整从基类接收的成员:☐通过继承方式改变基类成员在派生类中的访问属性。
☐同名覆盖(override): 派生类中重新定义与基类成员同名的新成员(函数原型说明相同),则可屏蔽基类的同名成员。
◆继承和派生的目的在于复用基类的某些属性,并对基类进行裁剪,以定制出适合于某种需要的新类。
关键字protected◆使用protected修饰的成员称为保护成员。
◆类中的保护成员只能被该类及其派生类和友元访问,其他不能访问。
◆private,protected,public称为可见性关键字(visibility keyword)或可访问性关键字(accessibility keyword)。
派生类的不同的继承方式决定了基类成员在派生类中的访问属性注意:无论哪种继承方式,在派生类中都不能访问基类的私有成员。
私有成员只能被本类的成员函数和友元函数访问,不能被其他(成员)函数访问公有继承◆当派生类的继承方式为公有继承时,基类各成员在派生类中的访问权限:☐公有成员:仍为公有,派生类的公有成员☐保护成员:仍为保护,派生类的保护成员☐私有成员:派生类不能访问,为基类私有◆派生类的成员只能访问基类中的public/protected成员,不能访问private成员。
◆派生类的对象(在派生类外)只能访问基类中的public成员。
◆公有继承基本保持了基类的访问属性,因此使用较多。
私有继承◆当类的派生方式为私有继承时:☐基类的所有public和protected的成员在派生类中的访问权限变为private☐基类的私有成员仍为基类私有。
即基类的公有成员和保护成员被派生类继承过来以后,成为了派生类的私有成员。
◆派生类的成员只能访问基类中的public/protected成员,而不能访问private成员◆派生类的对象不能访问基类中的任何成员保护继承◆当类的派生方式为保护继承时:☐基类的所有公有public和保护protected的成员在派生类中的访问权限变为protected☐基类的私有成员仍为基类私有。
◆基类中的公有和保护成员被派生类继承过来,作为派生类中的保护成员,基类的私有成员在派生类中不能直接使用。
◆派生类的成员也只能访问基类中的public/protected成员,而不能访问private成员。
◆派生类的对象不能访问基类中的任何成员。
保护继承和私有继承区别区别在于当把这些派生类当作基类去派生其他类时会产生不同结果。
用私有继承方式派生出来的类,从基类派生出来的公有和保护成员被当作这个类的私有成员,如果这个类去派生其他类,它派生出来的类的成员函数将无法访问这些私有成员; 采用保护方式派生出来的类从基类中继承的公有和保护成员被当作这个类的保护成员,如果用这个类去派生其他类,它的派生类的成员函数将可以直接访问这些成员。
§ 3 派生类的构造函数与析构函数**创建对象时要调用构造函数,对象消亡时要调用析构函数。
派生类不继承基类的构造函数和析构函数。
在创建派生类对象时,系统要调用派生类的构造函数,在执行派生类构造函数(体)前,系统要先调用其基类的构造函数以实现对从基类继承的数据成员的初始化,再执行派生类构造函数体以实现新增成员的初始化。
派生类对象消亡时,要调用派生类和基类的析构函数。
派生类构造函数的定义在派生类构造函数的定义中,在函数体前调用基类构造函数以实现对继承自基类数据成员的初始化。
调用基类的带指定实参的构造函数:DerivedClass( parameterList ) : BaseClass( argumentList ){// Perform initialization}☐调用基类的无参构造函数(可省略):DerivedClass( parameterList ) : BaseClass (){// Perform initialization}派生类构造函数名后面括号内的参数列表包括参数的类型和名称,而基类构造函数名后面括号内的参数表只有参数名,而无参数类型,因为这里是调用基类构造函数而不是定义基类构造函数,这些参数是实参而不是形参。
为派生类定义构造函数是否为派生类定义构造函数取决于基类。
在创建派生类对象时必然要调用基类和派生类的构造函数。
若基类有无参的构造函数(定义有无参的构造函数或者根本没有定义构造函数),则派生类可以不定义构造函数,或在构造函数中可以省略对基类构造函数的显式调用。
当创建派生类对象时系统会自动调用基类无参的构造函数。
若基类只有有参的构造函数,则派生类必须定义构造函数,并必须给出对基类构造函数的显式调用,以提供将参数传递给基类构造函数的途径。
因此有时派生类构造函数体可能为空,仅起到参数传递作用。
派生类使用基类无参的构造函数派生类可以不定义构造函数,或在构造函数中可以省略对基类构造函数的显式调用。
当基类中有无参构造函数或未显式定义构造函数时,派生类构造函数定义中可省略对基类构造函数的调用派生类使用基类有参的构造函数基类只有有参的构造函数,则派生类必须定义构造函数,并必须给出对基类构造函数的显式调用(为其提供实参数);否则产生编译错误。
因此有时派生类构造函数体可能为空,仅起到参数传递作用。
当基类中的构造函数中只有有参构造函数,则派生类构造函数中必须要显式调用基类的构造函数.派生类构造函数可以重载,以调用基类不同的构造函数.§ 4 派生类中新增成员与基类中成员同名◆在派生类中可以定义同基类中的成员同名的成员,则在派生类中有两个同名的成员:☐此时在派生类中基类的同名成员被屏蔽.☐若在派生类中访问基类被屏蔽的同名成员,则必须使用作用域运算符::以明确指定其所属的类.基类名::基类同名数据成员基类名::基类同名成员函数(实参列表)◆同名成员☐同名数据成员:同名☐同名成员函数:相同的函数原型声明(相同的返回类型、函数名、参数类型与个数),否则为函数重载而非同名。
§多态与虚函数1基类与派生类之间的转换C++有时在基类出现的地方需要派生类对象。
这时,就需要将派生类对象转换为基类对象。
在公有继承的情况下:◆赋值:派生类对象可以赋值给基类对象,这时是把派生类对象中从对应基类继承来的成员赋值给基类对象。
不允许将基类对象赋值给派生类对象(编译时报错,因为派生类的新成员无值可赋)。
derived d;base b;b=d;指针:可以将一个派生类对象的地址赋给其基类的指针变量,但只能通过这个指针访问派生类中由基类继承来的成员,不能访问派生类中的新成员。
derived d;base *pb=&d;◆引用:派生类对象可以初始化基类对象的引用。
但这个别名只能访问派生类对象中由基类继承来的成员。
derived d;base& br=b;◆特别是这三种情况为参数时:形参为基类,而实参可为派生类对象、指针或引用2 多态性(Polymorphism ,源于希腊语,含义为“多种形式”)◆一个函数可有多种实现形式。
同一个函数可通过多种方法进行调用(或用一个相同的名字定义具有不同实现的函数)。
◆由于1)派生类中同名函数的出现;2)基类指针可存放派生类对象地址和基类引用可作为派生类对象的别名,导致了派生类的多态。
C++中支持两种多态性,即静态多态和动态多态。
◆静态多态(也称静态绑定static binding):编译时的多态性,即在编译过程中决定了函数的确切调用,也叫静态联编.(例如根据基类指针的类型在编译时确定调用基类的函数;又如函数重载和运算符重载,编译系统根据重载函数的参数个数和类型的差别,在编译时就确定了程序中函数的调用与哪个函数绑定)◆动态多态(也称为动态绑定dynamic binding):在运行时确定调用哪个函数的能力称为动态绑定。
3 如何实现动态绑定?—虚函数为使函数能动态绑定,需要做两件事情(缺一不可):◆在基类中,函数必须声明为虚函数(virtual function);☐使用关键字virtual,指明该成员函数是虚函数。
(virtual只能出现在类声明中,在类实现_函数定义中不可再加virtual)☐在派生类中定义与基类的虚函数同名的函数,它仍为虚函数(当类中的某个成员函数被定义为虚函数后,则在该类所有的派生类中,该函数始终保持虚函数的特征,不必在派生类的函数声明中再使用关键字virtual。
) ☐虚函数必须是类的非静态成员函数◆使用基类的指针或引用:基类指针指向基类对象和派生类对象时;基类引用作为基类对象和派生类对象的别名时。
关于虚函数◆提示:什么样的成员函数应声明为虚函数?☐如果一个基类中定义的函数需要在派生类中重定义,应该将其声明为虚函数,以实现不同的功能。
☐如果一个函数不会被重定义,将其声明为非虚函数会更有效,因为在运行时动态绑定虚函数会花费更多的时间和系统资源。
◆派生类中定义与基类中虚函数的同名函数:具有相同的函数声明(函数类型、函数名、参数个数及参数类型)。
如果仅仅是名字相同,而参数类型、个数或函数的返回值类型不同,即使有virtual关键字,也不会实现动态绑定,此时实现的是静态绑定。