资源描述
c++复习摘要
第一部分——简单的程序设计
一、标识符(包括变量名命名规则)
1、定义:由数字、大小写字母和下划线组成
2、例子:
合法:Int(大小写不一样,不是关键字int)、_ab
不合法:new和friend(不能与关键字相同)、a+b(不能有+)、
2b(开头不能是数字)
二、 基本数据类型 存储空间 位数 存储形式
double 8 64 补码
int 4 32 补码
float 4 32 补码
char 1 8 ASCII码
特殊:指针*p 4(固定为long int类型)
string 16(固定大小)
注1:精度低—>自动转换—>精度高
注2:int a;a=8/3—>a=2(int整型)
三、 常量与变量
1、 八进制—>正负号和0开头,例:012、-057
十六进制—>正负号和0x或0X开头,例:0x34、-0X68
2、 字符常量
(1) 普通字符:‘A’、‘0’、‘#’、‘ ’(空格)
(2) 转义字符:‘\n’、‘\\’(表示\)、‘\0’
(3) ‘a’—>一个字节,“a”—>两个字节(包括‘/0’),长度为1
注:‘\ddd’—>表示八进制字符
‘\xdd’—>表示十六进制字符
例:strlen(“abc\\\120\0a s\0d”)和sizeof(“abc\\\120\0a sd”)的值
—>分析1:其中有a、b、c、\\、\120(八进制)、\0(碰到第一个则终止,且不计入长度),所以结果为5
—>分析2:算上所有的字符(包括\0,注意有个空格在a与s之间),结果为11(char字符占一个字节)
3、 指数:2e-6、-1.5E2(结尾加一个f(F),表示结果为float型)
注:e(E)后(即指数)必须是整数
四、 运算符和表达式
1、 算术运算符
+、-、/(不是\)、*(不可省略)、%(取余)
注1:++()、--(),其中()中必须是变量,不能是常量和表达式
例:5++、(a+b)++、++(2*i)——不合法
注2:int i=5,b;b=i++;—>b=5;i=6
int i=5,c;c=++i;—>c=6;i=6
2、 赋值运算符
(1) 区分“=”和“==”
(2) a+=b—>a=a+b
3、 关系运算符和逻辑运算符
(1)结果总为1或0
例1:t=5>4—>t=(5>4)—>5>4为真,则结果为1—>t的值为1
例2: a=1&&2—>a=(1!=0)&&(2!=0)—>a=1(&&运算优先级高)
4、 逗号运算符:表达式结果为最后一个逗号后的结果
例:a=3*5,a+5—>表达式结果为20
五、 语句
1、 if(a)—>if(a!=0)
2、 do whlie语句—>至少执行一次
例:do{ int i=1;j=0}while(a=b)
分析:先循环一次,由于条件为i=j—>(i=bj)!=0(不是a==b),则结果是无限循环
3、 switch语句不一定每个case后都有break(跳出当前循环语句,而不是if语句),default至多一个。
例:switch(a){case 1:cout<<’A’;break;
case 2:cout<<’B’
case 3:cout<<’C’;break;}
若输入a=2,则输出的结果为BC,程序从第二个开始执行,因为没有break跳出当前程序,会继续执行下面的程序,直到break跳出等。
4、 for循环:注意是否会无限循环(循环条件的正确性)
例:for(int x=0;x<=0;x--)—>无限循环
六、 补充
1、 continue—>跳过剩余语句(继续循环,不会跳出)
2、 const int a=5—>a的值不会再变(即a=6—>错误)
3、 运算符优先级
逻辑运算符(!>&&>||)>条件运算符(A?B:C) >值运算符(=、+=、*=)
4、 条件运算符—>A?B:C
例:5>4?3:2—>若A为真,则输出B,否则输出C,所以答案为3
第二部分——构造数据类型
一、 数组
1、 数组下标只能是常量(a[n]、a[]—>不合法)
2、 int a[20][20]—>数组未初始化,则元素的值不确定(除了静态数组未初始化时,默认是0)
int a[20][20]={0}—>元素全部为0,且每个元素都必须是int型的
注:a(5)—>a=5,上述数组最后一个元素为a[19][19]
3、 部分初始化:a[5]={1,2,3}—>a[5]={1,2,3,0,0}
二、 指针
1、’*’—>取内容,’&’—>取地址
int a[5]={0} , *p , p=&a[0](或p=a)
—>取出a中的首地址(即a[0])放在p中,则p中所存内容就是a[0]的首地址(*p—>即读取p中地址的内容—>就是a[0])
(1)cout<<p—>p本身的首地址
(2)cout<<&p—>取p中所存的地址,再输出—>a的首地址
(3)cout<<*p—>取p所存首地址的内容—>输出a[0]
(4)cout<<*(p+1)—>指针往后移动一位—>输出a[1]
注:*(p++)—>*(p+1)
2、动态内存分配
(1)int *p=new float[N]—>一维数组(这里N为变量)
int (*p)[4]=new float[3][4]—>二维数组
最后—>delete []p
三、 引用
1、 int r,&rv=r—>别名与目标名(即rv和r)共用内存
2、 类型必须一致,必须立即初始化(int &rv;—>错误)
例:int a;double &b=a;—>错误
3、 不能中途换名
例:int a,c;int &b=a,&c=b;—>错误
4、 数组引用:int a[5]={0};(&rv)[5]=a;
四、 字符串
1、 char s[20]=”c++程序设计”,*p=s;
(1) sizeof(s)—>一共可存放20个元素,每个都是char(占一个字节)—>结果为20
(2) sizeof(p)—>p是指针,一定为4个字节—>结果为4
(3) Strlen(s)—>”c++”为三个字节,”程序设计”(汉字是两个字节)为8个字节(不含’\0’)—>结果为11
注:char a[5]=”12345”—>错误(必须有一个位置放’\0’)
2、String
(1) string a=”man”,b=”kind”;—>a[1]=’e’—>a=”men”—>可以当作数组看
(2) 可以连接:c=a+b—>c=”mankind”
(3) 可以相互赋值:a=b—>a=”kind”
注:(2)和(3)都是char字符型数组所不能实现的
例:char a[5]=”c++”,b[6]=”hello”;a=b;—>错误
五、 其他类型
1、 枚举类型:enum
例:enum seasoon {spring,summer,autumn,winter};
season s=winter—>s=3;
分析:spring相当于0,后面逐次递增(可以对spring进行默认值设定,令spring=1,后面依次递增)
2、 结构体:struct—>类比——类与对象
3、 共用体:union
注:若干个成员中,其中占用内存最大的,作为共用体类型的大小(不是相加)
例:union a{int x;char s;}—>显然占4个字节(int),而不是char的1个字节
六、 补充
1、 char name[20]—>cout<<name—>输出为字符数组的内容
int name[20]—>cout<<name—>输出首地址
2、 char *p=”hello”(类比数组)
(1) cout<<*p—>h (2)cout<<p—>hello
(3) cout<<p+1—>ello—>指针向后移动一位,指向e,再输出后面的内容
3、 strcmp(s1,s2)—>进行大小比较
Strcpy(s1,s2)—>s1=s2(将s2的内容赋给s1)
S=strcat(s1,s2)—>将s1与s2的内容进行连接,再给S
第三部分——函数
一、 认识函数
1、 声明:int add(int a,int b);—>形参不占用空间,可省略为int add(int,int);(注意要有”;”)
调用:z=add(a,b)—>a,b均为实参(有内容)
例:z=swap(a+b,max(c),v)—>swap函数实参为3个(两个逗号)
2、c++的程序总是从main函数开始执行的
3、函数不允许嵌套定义,但是可以相互调用
4、有默认值的形参右边都要有默认值
例:int(int a,int b=0)—>合法
int(int a=0,int b)—>不合法
5、 引用传递:swap(int &x);—>x的值与函数结果有关
swap(int x);—>swap函数只是利用了x的值去运算,而未改变x本身的值
二、 简单函数
1、 递归函数(可简化程序,但时间和空间需求大)
例:阶乘—>int f(int n){if(n==1)return0;else return n*f(n-1);}
2、 内联函数(提高程序执行效率,以空间换时间):inline
例:inline int add(int a,int b){}—>只能包含一些简单的语句
3、 系统函数
例:sqrt(2)—>开方,fabs(-9)—>绝对值,rand()—>随机函数
4、 函数重载——功能相似
(1) 同名函数,但函数的参数类型、个数或者顺序不同
(2) 函数的返回值类型不能作为函数重载的区分条件
(3) 不能把功能不同的函数放在一起重载
三、 其他
1、 int a就相当于auto int a—>auto为自动变量,存放于动态存储区,可省略
2、 extern—>外部变量(属于全局变量),定义在函数体(包括mian函数)之外—>全局寿命
3、 static—>静态变量(未初始化时,就默认为0)—>有记忆功能(记住上一次运行结果)
第四部分——类与对象
一、 类与对象的认识
1、 c++通过类来实现封装
2、 面向对象程序设计的三个特征:封装性、多态性和继承性
3、 在类体内不能对数据成员进行初始化(因为没定义对象)
例:Class A{private:int data=2;}—>错误
二、 类成员
1、 private(私有成员)—>若开头省略,则默认为私有成员,只有该类的成员才能进行访问私有成员(派生类和对象都不能访问)
2、 protected(保护成员)—>允许派生类访问,不允许对象访问
3、 public(共有成员)—>定义了类的外部接口,允许派生类访问,并可以被对象进行调用
4、 成员函数类内声明—>settime(int a=0,int b=0){}—>类外定义—>void Clock::settime(int a=0,int b=0){}
三、 对象
1、 对象所占据内存只用于存放数据成员(如a、b等),类中函数代码在内存中只占据一份空间
2、 访问类型:Clock c,*time=&c,则有c.showtime()
或(*time).showtime或time->showtime()
四、 构造函数与析构函数
1、 构造函数—>对象的初始化
(1) 它是一个与类同名的成员函数,没有返回值,定义为公有函数,只能在定义对象是被系统内自动调用
(2) 类中可以有多个构造函数,构造函数可以被重载,可以是内联函数
(3) 带默认参数的构造函数
例:构造函数 Clock(int a=0,int b=0)—>Clock c1,c2(1),c3(1,1)—>均是正确的,如c2(1)等价于c2(1,0)
(4) 复制构造函数:Clock(Clock &c)
例:Clock c1;Clock c2(c1)—>Clock c2=c1
注1:Clock *p—>不会调用构造函数
Clock *p=&a—>出现对象a,则调用构造函数
注2:Clock a[4]={c1,c2,c3,c4}—>由于有4个元素都被类定义,故调用4次构造函数,程序结束时调用4次析构函数
五、 析构函数:~Clock()—>()中不能有参数
1、 析构函数属于公有成员,不能重载,但可以是虚函数
2、 当对象被删除或者程序结束时,自动调用析构函数
例:Clock *p=new Clock a;delete []p—>申请的空间被删除,则对象也消失,故调用一次析构函数
3、 一般情况下,调用几次构造函数,结束时就相反顺序调用几次析构函数
六、 友元:friend
1、实现不同类之间的数据共享,但破坏了类的封装性和隐蔽性
2、友元函数—>不属于类的成员函数,可以访问类的所有成员(包括私有成员)
3、友元类:如Class A{...friend Class B;...}—>意味着B类是A类的友元类—>B类的所有成员函数都可以访问A类的所有成员
4、友元关系不能传递且是单向的(A是B的友元函数,但B不是A的友元函数),友元关系不会被继承
七、其他
1、 this 指针:存在于类的成员函数中,用于区分数据成员(除静态数据成员外)
2、 静态成员:static
(1) 不属于某个对象,属于整个类(只能通过类名进行访问)
(2) 类外初始化,同样具有”记忆功能”
3、 const可用于对函数重载的区分
4、 类别 对象是否可以访问 派生类是否可以访问 private 否 否
protected 否 是
public 是 是
5、 类别 可以重载或内联 数量 是否可以有形参 构造函数 是 一或多 是
析构函数 否 一 否
注:均无返回类型(如int、double),析构函数可以是虚函数
第五部分——继承与派生
一、 继承
1、 若省略继承方式,则默认为私有继承
例:Class A:B—>Class A:private B
2、 派生类继承了基类除去构造函数和析构函数之外的全部数据成员和函数成员—>派生类中也有和基类一样的函数
3、 同名覆盖—>派生类中的新的同名函数覆盖基类的函数
4、 继承方式—>基类中的成员将在派生类中有的访问权限
例:Class B:protected A—>A中的成员在派生类中的访问权限是protected(故派生类的对象不能访问,派生类可以访问)
注:A中的public和protected在B中的访问权限都变成protected
注1:派生类的对象可以访问基类的public
注2:即使基内的private在派生类不可访问却仍然存在
注3:private属于”传递一代”,protected可以”多代传递”
二、 派生
1、 派生类的构造函数和析构函数
(1)例:Clock(int a,char b):Point(b)
注:派生类构造函数既要初始化派生类新增的成员,也要为他的基类的构造函数传递数据—>引用了基类的构造函数
(2) 派生类定义对象时,构造函数调用顺序:先基类—>内嵌对象—>最后派生类
例:Class B:public A{piblic:A a;}—>故先调用两次A的构造函数,在调用B的构造函数一次—>析构函数则反向执行
注:若为多继承Class C:public A,protected B—>则顺序执行A的构造函数,再是B的构造函数,最后是C的构造函数
2、 虚基类
(1) 消除多继承引起的二义性,消除数据冗余
(2) 通过虚基类继承,最后建立对象的类(称之为最远派生类),才调用虚基函数的构造函数—>保证对虚基类的对象只初始化一次
三、 其他
1、 若基类的构造函数有默认值,则派生类就不必给基类传递数据
例:Class A{A(int x=1){}};Class B{B(int y=1){}}—>而不必写成
Class B{B(int y,int x):A(x){}}
2、 积累与派生类的赋值兼容
(1) 派生类的对象可以赋值给基类对象—>就是派生类将基类的那部分赋值给基类—>反之不行
(2) 同一基类的不同派生类对象不能相互赋值(只是交集,不是包含关系)
总结:派生类可以对基类进行操作—>即(基类)=(派生类)的操作是对的,反之都是错的
例:Class A—>Class B:public A—>A a;B b;a=b(对)—>b=a(错误)
3、 判断是否可以访问
类别 基本身 派生类 派生类的对象 基的私有成员 是 否 否
基的保护成员 是 是 否
基的公有成员 是 是 是
第六部分——多态性
一、 编译时的多态:函数重载、运算符重载
运行时的多态:虚函数
二、 运算符重载:operator
1、 成员函数—— =、[]、()、—>(这些只能为成员函数)
例:加法—>类中声明:Complex operator+(Complex &c)—>类外定义:Complex::Complex operator+(Complex &c)—>函数的实现:c3=c1+c2
注:成员函数隐藏一个this指针,故参数比非成员函数少一个
2、 非成员函数:friend 函数返回值类型 operator运算符(形参表)
例:friend Complex operator+(Complex &c1,Complex &c2)
注:”>>”和”<<”只能重载为非成员函数
3、 规则和限制
(1) 只能对已有的c++运算符进行重载
例:ab、+++则是非法的
(2) 下列运算符不能重载
.(成员运算符)、*、::、?:、sizeof
(3) 重载不改变运算符的优先级、结构、操作个数—>只改变功能
(4) 重载函数不能有默认参数,且必须至少有一个类的对象
例1:Complex operator+(Complex &c=2)—>不合法
例2:Complex operator+(int &c)—>至少一个Complex类对象
(5) operator =(无形参)—>前缀一元运算符
(6) 对于++a,重载为成员函数—>a.operater++()
重载为非成员函数—>operator++(a)
对于a++,重载为成员函数—>a.operater++(0)
重载为非成员函数—>operator++(a,0)
注1:可知,成员函数的形参比非成员函数少一个(this的作用)
注2:某一填空题—>bool Bounce operator!(Bounce)
三、 虚函数
1、 例:A a,*p;B b;—>则基类对象的指针在指向派生类时,只会指向派生类中的基类部分(谁定义你,你就只与谁有关)
—>虚函数可以使基类中的函数”隐藏起来”,从而使指针指向派生类的同名函数
2、 只有类的成员函数才能是虚函数(构造函数不行,析构函数可以),非成员函数都不行,内联函数不行,静态函数不行
3、 必须为public继承,由”基类对象的指针或引用”去掉用基函数,才能实现动态绑定
四、 纯虚函数和抽象类
1、 纯虚函数:virtual void hello(int x)=0;
2、 一个类包含了纯虚函数,则为抽象类—>抽象类不能定义对象,只能为基类
3、 派生类若没给出基类的纯虚函数的函数实现(即定义一个与纯虚函数同名的有实际作用的函数)—>仍不能定义对象,还是一个抽象类(没有同名函数覆盖纯虚函数)
4、 虚析构函数—>使派生类的析构函数先执行,再执行基类的析构函数—>否则可能有内存泄漏(只执行了基类的析构函数)
展开阅读全文