面向对象程序设计复习纲要.docx
《面向对象程序设计复习纲要.docx》由会员分享,可在线阅读,更多相关《面向对象程序设计复习纲要.docx(21页珍藏版)》请在冰豆网上搜索。
面向对象程序设计复习纲要
2013面向对象程序设计复习纲要
1、基本题型与范围
1.1题型:
基础概念解释和问答、判断、填空、阅读程序写结果、单选、编写程序。
2.2内容覆盖:
面向对象基础概念和机制,封装、继承和多态(本部分内容为重点,含模板、运算符重载等)。
以面向对象课程为主。
2、课程基本内容一览
2.1一些术语的不同提法
基类——父类
派生类——子类
拷贝构造函数——复制构造函数
2.2类与对象
面向对象程序设计特点:
抽象、封装、继承、多态
Public、protected、private成员的区别(访问权限不同、继承方式不同)
构造函数、析构函数(析构函数既无参数也无返回值,故不能重载,即:
一个类中不可能有多个析构函数)
一个类,必须有构造函数、析构函数,即使不定义,系统将自动创建默认的函数
注意构造函数和析构函数是由系统自动调用,特别注意,构造函数可能有多个,到底调用哪一个,由定义对象时或使用new运算符时所给的参数确定
如果程序未创建拷贝构造函数,则系统也将自动创建默认的拷贝构造函数。
简单的说:
1、若未定义构造函数则系统将自动创建默认的无参构造函数
2、若未定义拷贝构造函数,则系统将自动创建默认的拷贝构造函数,此时的拷贝构造函数仅实现浅拷贝;
3、若未重载赋值运算,则当对象之间进行赋值时,系统将使用建默的=,此时的赋值仅实现浅拷贝;
问题:
1、什么是浅拷贝和深拷贝?
2、什么时候需要自定义拷贝构造函数?
(需要深拷贝:
自己体会什么时候需要深拷贝)
3、拷贝构造函数何时被调用?
(以下示例中point为一个类)
1)、当用类的一个对象初始化该类的另一个对象时。
例:
intmain()
{pointA(1,2);
pointB(A);//用对象A初始化对象B,拷贝构造函数被调用.
pointC=A;//此处等价于C(A),别误以为调用了赋值运算=,
}
2)、如果函数的形参是类的对象,调用函数时,进行形参和实参结合时。
例:
voidf(pointp)
{}
main()
{pointA(1,2);
f(A);//函数的形参为类的对象时,当调用函数时,拷贝构造函数被调用.
}
3)、如果函数的返回值是类的对象,函数执行完成返回调用者时。
例:
pointg()
{staticpointA(1,2);
returnA;//函数的返回值是类的对象,返回函数值时,调用拷贝构造函数.
}
voidmain()
{pointB;
B=g();
}
一个完整的程序:
//---------------------------------------------------------------------------
#include
//---------------------------------------------------------------------------
usingnamespacestd;
//---------------------------------------------------------------------------
classA
{
public:
A(){cout<<"A构造函数"<~A(){cout<<"A析构函数"<Aoperator=(Ab){cout<<"A重载的赋值运算"<//Aoperator=(A&b){cout<<"A重载的赋值运算"<A(A&b){cout<<"A拷贝构造"<};
//---------------------------------------------------------------------------
AFunc(Ab)//2:
传参调用拷贝构造
{
Aa;//3:
调用构造函数
a=b;//4:
注意,此处相当于首先调用函数operator=(Ab),再调用赋值运算
returna;//5:
拷贝构造,将a拷贝给Func将要返回给主调方的隐形对象。
然后析构对象a
}
//---------------------------------------------------------------------------
voidmain(void)
{
Aa;//1:
调用构造函数
a=Func(a);//2:
向Func传参调用拷贝构造,然后进入Func,然后赋值,然后析构Func返回的的隐形对象
system("pause");
//程序结束后,对象a将被析构
}
/*
程序完整输出:
A构造函数
A拷贝构造
A构造函数
A拷贝构造
A重载的赋值运算
A拷贝构造
A析构函数
A析构函数
A拷贝构造
A析构函数
A析构函数
A重载的赋值运算
A拷贝构造
A析构函数
A析构函数
A析构函数
*/
4、拷贝构造函数与赋值运算符(=)有何区别?
什么时候需要重载赋值运算符?
5、this指针
2.3C++程序结构
静态数据成员、静态函数成员各自的特点
友元函数、友元类,注:
友元关系是单向的,是给予而不是索取
常成员(参看文档)
2.4两个最重要的运算符及两个最重要的运算
1、2个运算符:
*&
2、New和delete运算
2.5继承与派生
Public、protected、private三种继承方式下,父类的Public、protected成员访问控制变化
如:
受保护继承时,父类的公有成员在子类中具有受保护成员特征
注意同名成员函数的不同处理机制,一个类中同名非虚成员函数属于重载关系,子类对父类的非虚成员函数进行重新定义的属于覆盖机制。
父类和子类之间具有泛化特化结构
要点:
1、子类、父类的构造函数、析构函数调用次序
2、子类的构造函数定义时,若需要使用父类的带参构造函数,如何定义(特别是多继承时时)?
3、同名隐藏、二义性问题及解决方法
4、虚基类,什么时候使用虚基类?
如何声明?
作用是什么?
(注意:
在第一级继承时就要将共同基类设计为虚基类)
2.6多态性
多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为。
多态的实现:
函数重载、运算符重载、虚函数
多态的类型:
重载多态、强制多态(静态绑定)、包含多态(通过虚函数实现,动态绑定)、参数多态(与类模板关联)
要求:
能进行运算符的重载,理解并使用虚函数,纯虚函数,抽象类
2.7函数模板和类模板
掌握基本概念(见PPT),能使用函数模板和类模板进行简单的程序设计
2.8异常处理
掌握基本概念(见PPT)
2.9文件流
掌握基本概念(见Word文档)
3、模拟试题
一、填空题
1、当建立对象时,程序自动调用该类的;当撤销对象时,程序自动调用该类的。
2、当定义重载函数时,应在上有所不同。
3、类是自定义的类型,具有类类型的变量称作。
4、在一个类中,多个同名非虚成员函数之间构成关系。
5、拷贝构造函数通过使用引用来初始化创建中的对象。
6、基类的公有成员在私有派生类中是__________成员,基类的保护成员在公有派生类中是__________成员。
7、带有的类称为抽象类,抽象类不能。
8、如果类的名称是MyClass则析构函数名为__________,一个类最多能有__________个析构函数。
9、将关键字__________写在函数体之前函数头之后,说明该函数是一个__________,可以防止函数改变数据成员的值。
10、多态的实现方式有:
函数重载、运算符重载和;多态的类型有重载多态、强制多态、和。
11、在一个类中,多个同名非虚成员函数之间构成关系。
12、子类对父类的非虚成员函数进行重新定义的机制称为。
13、受保护继承时,父类的公有成员在子类中具有成员特征。
二、单项选择题
1、下列关于构造函数的描述中,错误的是()
A、构造函数可以设置默认参数; B、构造函数在定义类对象时自动执行
C、构造函数可以是内联函数; D、构造函数不可以重载
2、下面有关重载函数的说法中正确的是()
A、重载函数必须具有不同的返回值类型; B、重载函数形参个数必须不同;
C、重载函数必须有不同的形参列表 D、重载函数名可以不同
3、下面描述中,错误的是()
A、公有继承时基类中的public成员在派生类中仍是public的
B、公有继承是基类中的private成员在派生类中仍是private的
C、公有继承时基类中的protected成员在派生类中仍是protected的
D、私有继承时基类中的public成员在派生类中是private的
4、在下列程序划线处填入的正确语句是()
class Base
{ public:
void fun(){cout<<"Base:
:
fun"<};
class Derived:
public Base
{ void fun()
{_____________ //显式调用基类的函数fun()
cout<<"Derived:
:
fun"< }
};
A、fun() B、Base.fun(); C、Base:
:
fun() D、 Base->fun();
5、有如下程序:
class BASE{
private:
char c;
public:
BASE(char n):
c(n){}
virtual~BASE(){cout<};
class DERIVED:
public BASE{
private:
char c;
public:
DERIVED(char n):
BASE(n+1),c(n){}
~DERIVED(){cout<};
int main()
{ DERIVED(‘X’);
return 0;
}
执行上面的程序将输出()
A、XY B、YX C、X D、Y
6、指C++中解决命名冲突的机制是:
A、虚基类B、虚函数C、函数重载D、名字空间
7、在下列说法中,不正确的是()。
A、静态成员函数不能利用this指针
B、只有非静态成员才可以使用this关键字,因为静态成员没有this指针
C、析构函数不接受任何参数,也不带有任何类型的返回值
D、虚机制在构造函数和析构函数中仍然可以很好地工作,以实现多态性
8、在函数定义前加上关键字“inline”,表示该函数被定义为()
A、重载函数B、内联函数C、成员函数D、普通函数
9、下面的类说明中有()个语法错误
classss{intdata=3;
public:
intss(intx=0);
~ss(intx);
};
A、1B、2C、3D、4
10、在C++语言中,为了使重载函数具有通用的函数体,应使用()
A.虚函数B.纯虚函数C.函数模板D.友元函数
11、下列各个成员函数中,纯虚函数是()
A.voidfun(int)=0B.virtualvoidfun(int)
C.virtualvoidfun(int){}D.virtualvoidfun(int)=0
12、为了使类中的某个成员不能被类的对象通过成员操作符访问,则不能把该成员的访问权限定义为()
A.publicB.protectedC.privateD.static
13、不能作为函数重载判断依据的是()
A.constB.返回类型C.参数个数D.参数类型
14、下列运算符中,()运算符在C++中不能重载(4分)
A.&&B.[]C.:
:
D.new
15、以下关于类和对象叙述正确的是()
A.只有通过具体的对象才能访问类的成员函数
B.一个类的成员函数可以任意被调用
C.对象是抽象的,而类是具体实现
D.类和对象间没有联系
16、一个类的友元函数或友元类能够通过成员操作符访问该类的()
A.私有成员B.保护成员C.公有成员D.所有成员
17、若Myclass为一个类,则执行Myclassa[3],*p[2];语句时,自动调用该类构造函数()次
A.2B.3C.4D.5
18、在()情况下宜采用inline定义内联函数
A.函数体含有循环语句B.需要加快程序的执行速度
C.函数体含有递归语句D.函数代码多,不常被调用
19、如果类A被说明成类B的友元,则()
A.类A的成员即类B的成员B.类B的成员即类A的成员
C类A的成员函数不得访问类B的成员.D.类B不一定是类A的友元
20、定义析构函数时,应注意()
A.其名与类名完全相同B.返回类型是void类型
C.无形参,也不可重载D.函数体中必须有delete语句
21、以下有关继承的叙述正确的是()
A.构造函数和析构函数都能被继承
B.派生类是基类的组合
C.派生类对象除了能访问自己的成员以外,不能访问基类中的所有成员
D.基类的公有成员一定能被派生类的对象访问
22、类MyA的拷贝初始化构造函数是()
A.MyA()B.MyA(MyA*)
C.MyA(MyA&)D.MyA(MyA)
23、以下关于抽象类的描述正确的是()
A.不能说明指向抽象类对象的指针或引用
B.可以说明抽象类对象
C.抽象类的纯虚函数的实现可以由自身给出,也可以由派生类给出
D.抽象类的纯虚函数的实现由派生类给出
24、下列关于静态数据成员的描述中正确的是()
A.静态数据成员是类的所有对象所共有的
B.静态数据成员要在构造函数内初始化
C.类的每个对象有自己的静态数据成员
D.静态数据成员不能通过类的对象调用
25、下列虚基类的说明中,正确的是()
A.classvirtualY:
publicXB.classY:
virtualpublicX
C.virtualclassY:
publicXD.classY:
publicXvirtual
三、判断题
1、构造函数可以重载,析构函数也可以重载。
()
2、析构函数可以是虚函数,构造函数不能是虚函数。
()
3、含有纯虚函数的类可以创建对象。
()
4、当一个类中没有定义构造函数时,该类没有构造函数。
()
5、static成员不占用对象空间。
()
6、友元关系是给予的,而不是索取的。
()
7、运算符重载是多态的一种形式。
()
四、程序填空(2分×8=16分,假设所需的头文件均已经包含)
1、下面是对日期类Date的定义。
但类Date的定义并不完整.请按要求完成下列操作,将类Date的定义补充完整:
classDate{
private:
int:
year,month,day;
public:
【1】//完成默认构造函数Date的定义,使Date对象的默认值//为:
year=1,month=1,day=1
Date(inty,intm,intd)
{
【2】//重载构造函数Date(inty,intm,int)的定义,把数据
//成员year,month和day分别初始化为参数y,m,d的值
}
voidprint()const;
};
voidDate:
:
print()const
{
【3】//完成成员函数print的类外定义,使其以"年-月-日"的
//格式将Date对象的值输出到屏幕上
}
2、在下面横线处填上适当字句,完成求最大值函数模板的定义
template
TMax(Tx,Ty)
{
return(x>y?
x:
y);
}
【4】
TMax(Tx,Ty,Tz)
{
Tt=Max(x,y);
return(【5】);
}
voidmain()
{
intx;doubley;
x=Max(5,6);y=Max(12.3,3.4,7.8);
cout<<"x="<}
3、以下的类ArrayFloat是定义的一个浮点数组,请填空完成
classArrayFloat
{
protected:
float*pA;
intSize;//数组大小(元素个数)
public:
ArrayFloat(intsz=10){Size=sz;pA=newfloat[Size];}
~ArrayFloat()
{
【6】;//释放动态内存
}
intGetSize(void){returnSize;}
float【7】//重载数组元素操作符[]
{returnpA[i];}
voidPrint();
};
voidArrayFloat:
:
Print()
{
for(inti=0;【8】;i++)//在屏幕上显式所有的数组元素
{
if(i%10==0)cout<cout<}
}
4、以下程序运行后输出结果是:
1234,请填空完成。
classA
{
intx;
public:
A(inta){x=a;}
intgetx(){returnx;}
};
classB:
publicA
{
inty;
Aa1,a2;
public:
B(inta,intb,intc,intd):
A(a),a1(c),a2(d){y=b;}
intgety(){returny;}
intget1(){returna1.getx();}
intget2(){returna2.getx();}
};
voidmain()
{
Bb(1,2,3,4);
cout<}
5、填空完成以下程序。
intf(inta,intb)
{
if(a==0&&b!
=0)throwexception("OK");
returna/b;
}
voidmain()
{
inta,b;cin>>a>>b;
try
{
cout<cout<<"Gohere!
"<}
catch(exception&e)
{
cout<}
catch(...)
{
cout<<"Dividebyzero!
"<}
}
6、以下程序运行后输出结果是:
1234,请填空完成。
classA
{
private:
intx;
public:
A(inta){x=a;}
intgetx(){returnx;}
};
classB:
publicvirtualA
{
private:
inty;
public:
B(inta,intb):
A(a){y=b;}
intgety(){returny;}
};
classC:
publicvirtualA
{
private:
inty;
public:
C(inta,intb):
A(a){y=b;}
intgety(){returny;}
};
classD:
publicB,publicC
{
private:
intz;
public:
D(inta,intb,intc,intd):
B(0,b),C(0,c),z(d),A(a){}
intgetz(){returnz;}};
voidmain(){
Dd(1,2,3,4);
cout<:
gety()<:
gety()<}
7、
classA{
inty[100];
public:
A(int*b){for(inti=0;i<100;++i)y[i]=b[i];}
intoperator[](inti){returny[i];}
};
voidmain(){
intb[100],i;
for(i=0;i<100;++i)b[i]=2*i;
Aa(b);
for(i=0;i<100;++i)cout<}
五、程序分析(假设所需的头文件均已经包含)
1、下面程序实现输出半径为2.5的圆的面积,但输出结果是0,找出原因并提出修改意见。
constfloatpi=3.14159f;
classpoint{
private:
floatx,y;
public:
floatarea(){return0.0;}
};
classcircle:
publicpoint{
private:
floatradius;
public:
voidsetRadius(floatr){radius=r;}
floatarea(){returnpi*radius*radius;}
};
voidmain()
{point*p;
circlec;
c.setRadius(2.5);
p=&c;
cout<<"Theareaofcircleis"<area()<}
错误及修改:
【1】
2、下面程序中有一处错误,请指出错误所在并说明出错原因。
classA{
private:
intx;
friendclassB;
};
classB{};
classC:
publicB{
voidfunc(A*p