面向对象期末整理.docx
《面向对象期末整理.docx》由会员分享,可在线阅读,更多相关《面向对象期末整理.docx(35页珍藏版)》请在冰豆网上搜索。
面向对象期末整理
面向对象期末整理
第三章函数(function)
1、回文数判断
boolsymm(longn){
longi,m;
i=n;m=0;
while(i){
m=m*10+i%10;
i=i/10;
}
return(m==n);
}
2、嵌套调用
intfun1(intx,inty){
intfun2(intm);
return(fun2(x)+fun2(y));
}
intfun2(intm){
return(m*m);
}
*函数不允许嵌套定义,但可以嵌套调用。
3、递归法:
从n个人中选择k个人组成一个委员会的不同组合数。
intcomm(intn,intk){
if(k>n)
return0;
elseif(n==k||k==0)
return1;
else
returncomm(n-1,k)+comm(n-1,k-1);?
}
4、在函数被调用时才分配形参的存储单元。
实参可以是常量、变量或表达式。
传递时是传递参数值,即单向传递
5、引用是为对象取一个别名,不占存储空间。
引用类型说明符为&。
声明一个引用型变量时,必须同时使之初始化,即声明它代表那一个变量。
并且从此不可改变。
6、内联函数inline
功能简单,规模小,使用频繁的函数。
不能进行异常接口声明
7、带默认形参值的函数
√intadd(intx,inty=5,intz=6);
Xintadd(intx=1,inty=5,intz);
Xintadd(intx=1,inty,intz=6);
intadd(intx=1,inty=2);
voidmain()
{intadd(intx=3,inty=4);
add();//使用局部缺省形参值(实现3+4)
}
voidfun(void)
{...
add();//使用全局缺省形参值(实现1+2)
}
8、函数重载
9、头文件cmath
sin()、cos()、tan(),
求平方根函数(sqrt)、求绝对值函数(abs)等。
第4章类与对象
1、面向过程的程序设计方法
形式:
主模块+若干子模块。
特点:
自顶向下、逐步求精—功能的分解。
缺点:
a、程序员必须要建立起机器模型(位于解空间)和实际待解决问题模型(位于问题空间)间的联系;b、维护代价高;c、程序可重用性相对差。
2、面向对象的方法
目的:
实现软件设计的产业化。
观点:
自然界是由实体(对象)所组成。
使程序员不会受限于特定类型的问题。
程序设计方法:
使用面向对象的观点来描述模仿并处理现实问题。
通过添加新类型的对象,使自身适用于某个特定问题。
OOP根据问题来描述问题,而可以不需要根据运行解决方案的计算机来描述问题。
要求:
高度概括、分类、和抽象。
3、OOP的基本特点:
抽象
数据抽象;行为抽象(功能抽象、代码抽象)。
抽象的实现:
通过类的声明。
封装
形成“类”。
目的是增强安全性和简化编程
实现封装:
类声明中的{}
继承与派生
支持层次分类的机制。
在保持原有类特性的基础上,进行更具体和详细的说明。
实现:
声明派生类——第七章
多态性?
多态:
同一名称,不同的功能实现方式。
目的:
达到行为标识统一,减少程序中标识符的个数。
实现:
重载函数和虚函数——第八章
4、关键字protected后面声明的保护类型
与private类似,其差别表现在继承与派生时对派生类的影响不同(第七章)。
5、对象:
类类型的变量。
对象所占据的内存空间,仅用于存放数据成员,函数成员不在每个对象中存储副本
6、类外给出函数体实现:
用类名加以限定
voidClock:
:
setTime(…){…}
*也可以直接在类中给出函数体,形成内联成员函数(隐式)。
显式:
7、结构体的声明和初始化
structSavings{
unsignedaccountNumber;
floatbalance;
};
SavingsA={1,2000.0};
8、构造函数(Constructor)
在对象创建时由系统自动调用
重载构造函数的实现:
Clock:
:
Clock(intnewH)
{hour=newH;}
Clock:
:
Clock()
{hour=0;}
9、复制构造函数(CopyConstructor)
classPoint{
public:
Point(intxx=0,intyy=0){x=xx;y=yy;}
Point(Point&p);
……
};
Point:
:
Point(Point&p){
x=p.x;
y=p.y;
cout<<"复制构造函数被调用"<}
*复制构造函数被调用的3种情况
※Pointb(a);//复制构造函数被调用
※Pointa(1,2);
fun1(a);//调用复制构造函数
※Pointg()
{Pointa(1,2);
returna;//函数的返回值是类对象调用复制构造函数
}
*默认复制构造函数:
用作为初始值的对象的每个数据成员的值,初始化将要建立的对象的对应数据成员。
10、析构函数(Destructor)
完成对象被删除前的一些清理工作。
在对象的生存期结束的时刻系统自动调用它,然后再释放此对象所属的空间。
(常量:
constfloatPI=3.14159f;)
classPoint{
public:
~Point();
…
};
Point:
:
~Point(){
cout<<“调用了析构函数!
”<}
//带缺省参数构造函数
//构造函数重载
//析构函数&默认复制构造函数
//复制构造函数
11、类的组合
classLine{
public:
//外部接口
Line(Pointxp1,Pointxp2);
Line(Line&l);
doublegetLen(){returnlen;}
private:
//私有数据成员
Pointp1,p2;//Point类的对象doublelen;
};
//组合类的构造函数
Line:
:
Line(Pointxp1,Pointxp2):
p1(xp1),p2(xp2){
cout<<"Line构造函数被调用"<doublex=double(p1.getX()-p2.getX());
doubley=double(p1.getY()-p2.getY());
len=sqrt(x*x+y*y);
}
*构造函数调用顺序:
先调用内嵌对象的构造函数,然后调用本类的构造函数。
//组合类的复制构造函数
Line:
:
Line(Line&l):
p1(l.p1),p2(l.p2){cout<<"Line复制构造函数被调用"<len=l.len;}
intmain(){
Pointmyp1(1,1),myp2(4,5);//建立Point类的对象
Lineline(myp1,myp2);//建立Line类的对象
Lineline2(line);//利用复制构造函数建立一个新对象
cout<<"Thelengthofthelineis:
";
cout<cout<<"Thelengthoftheline2is:
";
cout<return0;
}
12、前向引用声明
当你使用前向引用声明时,你只能使用被声明的符号,而不能涉及类的任何细节。
第五章数据保护与共享
1、作用域:
是标识符的有效范围(函数原型作用域;局部作用域;类作用域;命名空间作用域)。
可见性:
标识符是否可以引用的问题(程序运行到某一点。
能够引用到的标识符,就是该处可见的标识符。
可见性表示从内层作用域向外层作用域“看”时能看见什么。
)。
特例:
#include
usingnamespacestd;
intmain(){
intj=1;
for(inti=0;i<5;i++){
}
cout<
/*VC6.0并未实现c++标准,而是沿用了c的习惯。
在c++标准中,上述i的作用域仅在for循环中。
*/
return0;
}
2、对类X的成员m(具有类作用域)的访问方式:
如在X的成员函数中,没有声明同名的局部变量,在该函数中,可以直接访问m;
通过x.m或者X:
:
m(x为X的实例对象);通过表达式ptr->m,(ptr为指向X类的对象的指针)。
3、命名空间作用域
用using来指定命名空间:
usingNS:
:
File;//在当前作用域中就可以直接引用File
usingnamespacestd;//在当前作用域,命名空间std中的所有标识符,都可直接引用
*具有命名空间作用域的变量,也称为全局变量
#include
usingnamespacestd;
inti;//在全局命名空间中的全局变量
namespaceNs{
intj;//在Ns命名空间中的全局变量
}
例子:
4、作用域可见性的一般规则:
标识符A、声明在先,引用在后
B、外层声明、内层无同名,则在内层可见。
C、外层声明、内层同名,则在内层不可见。
5、对象的生存期
静态生存期:
命名空间作用域中声明,函数内部声明加关键字static。
动态生存期:
局部作用域中声明。
6、类的静态成员:
用关键字static声明
描述类的所有对象的共同特征的一个数据项,对于任何对象实例。
它的属性值是相同的。
静态数据成员:
该类的所有对象维护该成员的同一个拷贝;必须在类外定义和初始化,用(:
:
)来指明所属的类。
静态成员函数:
类外代码可以使用类名和作用域操作符(:
:
)或对象名来调用静态成员函数。
静态成员函数只能引用属于该类的静态数据成员或静态成员函数。
*静态成员属于类,非静态成员属于对象。
#include
usingnamespacestd;
classPoint{
public:
Point(intxx=0,intyy=0){x=xx;y=yy;count++;}
~Point(){count--;}
staticvoidshowCount()
{cout<//……
private:
//……
staticintcount;//引用性说明
};
intPoint:
:
count=0;//定义性说明,初始化
voidmain(){
Point:
:
showCount();////输出对象数,类名引用
Pointa(4,5);//声明对象a
a.showCount();//输出对象数,对象名引用
//……
}
7、类的友元:
关键字friend
不同类或对象之间、类的成员函数与一般函数之间,进行数据共享的机制;
破坏了数据封装和数据隐藏。
访问对象中的成员,必须通过对象名。
//友元函数
frienddoubledist(Point&p1,Point&p2);
doubledist(Point&a,Point&b){
doublex=a.x-b.x;
doubley=a.y-b.y;
returnsqrt(x*x+y*y);
}
friendvoidTeacher:
:
setGPA(Student&s);
voidTeacher:
:
setGPA(Student&s){
s.gpa=4.0
}
//友元类
B类声明为A类的友元,
即,B类的所有函数(包括构造函数和析构函数)成为A类的友元。
类B的所有成员都能访问类A的私有成员。
友元关系:
不能传递的、单向的、不被继承的。
8、共享数据的保护(常**)
常对象必须进行初始化,且不能被更新
常数据成员只能通过初始化列表赋初值。
voidprint()const;//常成员函数声明
voidR:
:
print()const{//常成员函数实现
cout<}
常引用:
const类型说明符&引用名
(常引用做形参,在函数中不能更新r所引用的对象)
9、多文件结构
类声明文件(.h文件)
类实现文件(.cpp文件)
类的使用文件(main()所在的.cpp文件)
10、编译预处理命令
#include包含指令:
#include<文件名>,#include"文件名"(当前目录)
#define宏定义指令
#if和#endif,#else,#elif,#ifdef,#ifndef,条件编译指令
预处理操作符—defined(返回:
0,非0)
或
第六章数组、指针与字符串
1、数组
数组属于构造类型。
下标表达式必须为整数。
数组名是一个常量,不能被赋值。
inta[3][4]={{1},{0,6},{0,0,1,1}};
数组名作参数,形、实参数都应是数组名,传送的是数组首地址。
Pointa[2]={Point(1,2),Point(3,4)};
2、指针
指针运算符“*”
声明:
表示声明的是指针
执行或初始化:
表示指针所指对象的内容
地址运算符“&”
声明:
表示声明的是引用。
出现在变量赋值时,出现在等号右边;或在执行语句中作为一元运算符出现:
表示取对象的地址。
int*pa,*pb=&b;pa=&a;
3、指向常量的指针:
指针类型的常量:
void*pv;int*pint;
pint=(int*)pv;
*pa就是a[0],*(pa+1)就是a[1]
cout<<*(*(array2+i)+j);
//cout<<*(array2[i]+j);
例6—11
4、对象指针声明
类名*对象指针名;
例:
Pointa(4,5);
Point*ptr;
ptr=&a;
访问:
对象指针名->成员名
cout<<(*ptr).getX();
cout<getX();
cout<5、this指针
非静态成员函数
6、int(Point:
:
*funcPtr)()const;
funcPtr=&Point:
:
getX;
cout<<(a.*funcPtr)()<cout<<(p1->*funcPtr)()<cout<cout<getX()<7、动态内存分配
int*ptr;=newint
(2);//初值为2
deleteptr;
//数组:
int*ptr=newa[c][2];
delete[]ptr;
内存泄漏
8、头文件:
和
(1)动态存储分配函数:
void*malloc(size);
size:
字节数
返回值:
成功,则返回void型指针。
失败,则返回空指针。
(2)动态内存释放函数
voidfree(void*memblock);
参数memblock:
指针,指向需释放的内存。
返回值:
无
s=malloc(5000);/*申请内存空间*/
free(s);
9、深复制与浅复制
深复制是在浅复制基础上添加复制构造函数(内有Point*point=newPoint[size])。
例6-21,例6-22
10、字符串
string类
strcat(连接),strcpy(复制),
strcmp(比较),strlen(求长度),
strlwr(转换为小写),
strupr(转换为大写)
头文件
第七章继承与派生
1、继承的目的:
实现代码重用。
派生的目的:
当新的问题出现,原有程序无法解决(或不能完全解决)时,需要对原有程序进行扩展和改进。
2、派生类的声明
classDerived:
privateBase1,publicBase2{
public:
Derived();
~Derived();
//派生类的其它成员
};
3、派生类的生产过程
吸收基类成员(除构造函数和析构函数外);改造基类成员(覆盖或隐藏);
添加新成员(核心);
4、继承方式
派生类中的成员函数不能访问基类的private成员。
基类的private成员不可直接访问。
public:
通过派生类的对象只能访问基类的public成员。
private:
通过派生类的对象不能访问基类中的任何成员。
若对象将访问该函数(如getY()),定义时写为Point:
:
getY();}
protected:
通过派生类的对象不能访问基类中的任何成员。
特点:
(水平访问)通过基类对象不能访问其protected成员。
(垂直访问)在派生类的成员函数中,可以访问其基类的protected成员。
5、类型兼容规则
替代:
派生类对象只能使用从基类继承的成员。
例子
voidfun(Base1*ptr){ptr->display();}
intmain(){
Base1b1;Base2b2;Derivedd;
fun(&b1);
fun(&b2);
fun(&d);
}
结果:
Base1:
:
display()
Base1:
:
display()
Base1:
:
display()
6、派生类的构造函数
调用基类的构造函数初始化;
初始化派生类新增的成员对象;
执行派生类构造函数体。
C:
:
C(inti,intj):
B(i),c(j){}
多继承且有内嵌对象时:
classC:
publicB2,publicB1,publicB3{
public:
//派生类的公有成员
C(inta,intb,intc,intd):
B1(a),memberB2(d),memberB1(c),B2(b){}
private:
//派生类的私有对象成员
B1memberB1;
B2memberB2;
B3memberB3;
};
7、派生类的复制构造函数
Derived:
:
Derived(constDerived&v):
Base(v){…………}
8、继承时的析构函数
在6的例子的三个基类中声明析构函数,系统会自动隐式调用。
9、派生类成员的标识与访问
同名隐藏原则。
如要通过派生类对象访问基类中被覆盖的同名成员,应使用基类名限定。
d.B1:
:
var=2;
d.B1:
:
fun();
10、二义性问题
多继承时,基类与派生类之间,或基类之间出现同名成员时,将出现访问时的二义性(不确定性)——采用虚函数或同名隐藏原则来解决。
第八章多态性
1、多态性:
发出同样的消息,被不同类型的对象接收时,导致完全不同的行为。
多态是对类的特定成员函数的再抽象。
消息:
对类的成员函数的调用。
绑定(binding):
是指计算机程序自身彼此关联的过程。
绑定确定程序中的操作调用与执行该操作的代码间的关系。
静态绑定:
绑定工作在编译连接阶段完成。
如:
重载、强制和参数多态
动态绑定/晚期绑定:
绑定在程序运行阶段完成。
2、运算符重载:
对已有的运算符赋予多重含义(以适用于用户自定义类型)。
不能重载的运算符..*:
:
?
:
经重载的运算符,其操作数中至少应该有一个是自定义类型。
声明形式
返回类型operator运算符(形参){
......
}
重载为类成员函数时:
参数个数=原操作数个数-1(后置++、--除外)
重载为非成员函数(一般声明为类的友元函数):
参数个数=原操作数个数
Complexoperator+(constComplex&c2);
//+重载为成员函数
ComplexComplex:
:
operator+
(constComplex&c2){//重载函数实现
Complexc;
c.real=c2.real+real;
c.imag=c2.imag+imag;
returnComplex(c.real,c.imag);
}
//
friendComplexoperator+(constComplex&c1,constComplex&c2);//运算符+重载
friendostream&operator<<(ostream&out,constComplex&c);//运算符<<重载
Complexoperator+(constComplex&c1,constComplex&c2){//运算符+重载
return
Complex(c2.real+c1.real,c2.imag+c1.imag);
}
ostream&operator<<(ostream&out,constComplex&c){//运算符<<重载
out<<"("<returnout;
}
/*前置单目运算符,重载函数没有形参;
对于后置单目运算符,重载函数需要有一个整型形参。
*/
Clock&Clock:
:
operator++(){
//前置单目运算符重载函数
second++;
……
return*this;
}
ClockClock:
:
operator++(int){
//后置单目运算符重载
Clockold=*this;
++(*this);
returnold;
}
**程序运行结果为:
Firsttimeoutput:
23:
59:
59
myClock++:
23:
59:
59
++myClock:
0:
0:
1
3、虚函数virtual
虚函数是动态绑定的基础。
是非静态的成员函数。
具有继承性,本质:
是覆盖
*
实现这种动态的多态性,必须使用基类类型的指针变量或引用,使该指针指向不同的派生类的对象,并通过调用指针所指的虚函数才能实现动态的多态性。
派生类中定义的虚函数,必须与基类中的虚函数同名,参数的类型、顺序、个数必须一一对应。
只有类的成员函数才能说明为虚函数,普通函数不能说明为虚函数。
一般内联函数不应是虚函数,因为内联函数是在编译时决定其位置。
构造函数不能是虚函数。
析构函数可以是虚函数。
4、纯虚函数
这样基类中就可以不需要给出函数的实现部分。
5、抽象类
抽象类只能作为基类来使用,不能声明对象,
可以定义指针或者引用