voidf(){cout<<”C'sf()."<〈endl;}
};
voidmain()
{ A*a=newC;
a->g();
deletea;
}
运行结果:
A'scons.
A’sf().
B’scons.
C'scons.
C'sf()。
C’sdes。
B’sdes。
A'sdes。
10.3教材习题解答
1.选择题
(1)下列关于动态联编的描述中,错误的是()。
A.动态联编是以虚函数为基础
B.动态联编是运行时确定所调用的函数代码的
C.动态联编调用函数操作是指向对象的指针或对象引用
D.动态联编是在编译时确定操作函数的
答案:
D
(2)关于虚函数的描述中,正确的是()。
A.虚函数是一个静态成员函数
B.虚函数是一个非成员函数
C.虚函数即可以在函数说明定义,也可以在函数实现时定义
D.派生类的虚函数与基类中对应的虚函数具有相同的参数个数和类型
答案:
D
(3)下面4个选项中,( )是用来声明虚函数的。
A.virtual B.public C.using D.false
答案:
A
(4)编译时的多态性可以通过使用( )获得。
A.虚函数和指针 B.重载函数和析构函数 C.虚函数和对象 D.虚函数和引用
答案:
A
(5)关于纯虚函数和抽象类的描述中,错误的是( )。
A.纯虚函数是一种特殊的虚函数,它没有具体的实现
B.抽象类是指具体纯虚函数的类
C.一个基类中说明有纯虚函数,该基类派生类一定不再是抽象类
D.抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出
答案:
B
(6)下列描述中,( )是抽象类的特征.
A.可以说明虚函数 B.可以进行构造函数重载 C.可以定义友元函数 D.不能说明其对象
答案:
D
(7)以下( )成员函数表示虚函数。
A.virtualintvf(int); B.voidvf(int)=0;
C.virtualvoidvf()=0; D.virtualvoidvf(int){};
答案:
D
(8)如果一个类至少有一个纯虚函数,那么就称该类为(A )。
A.抽象类 B.虚函数 C.派生类 D.以上都不对
答案:
A
(9)要实现动态联编,必须通过( )调用虚函数。
A.对象指针 B.成员名限定 C.对象名 D.派生类名
答案:
A
(10)下面描述中,正确的是(A )。
A.virtual可以用来声明虚函数
B.含有纯虚函数的类是不可以用来创建对象的,因为它是虚基类
C.即使基类的构造函数没有参数,派生类也必须建立构造函数
D.静态数据成员可以通过成员初始化列表来初始化
答案:
A
2.什么叫做多态性?
在C++语言中是如何实现多态的?
答:
多态是指同样的消息被不同类型的对象接收时导致完全不同的行为,是对类的特定成员函数的再抽象.c十+支持的多态有多种类型.重载(包括函数重载和运算符重载)和虚函数是其中主要的方式.
3.什么叫做抽象类?
抽象类有何作用?
抽象类的派生类是否一定要给出纯虚函数?
答:
带有纯虚函数的类是抽象类.抽象类的主要作用是通过它为一个类族建立一个公共的接口.使它们能够更有效地发挥多态特性。
抽象类声明了一组派生类共同操作接口的通用语义.面接口的完整实现,即纯虚函数的函数体,要由派生类自己给出.但抽象类的派生类并非一定要给出纯虚函数的实现.如果派生类没有给出纯虚函数的实现,这个派生类仍然是一个抽象类.
4.声明一个参数为整型、无返回值、名为fun1的虚函数。
答:
virtualvoidfnl(int);
5.在C++语言中,能否声明虚构造函数?
为什么?
能否声明虚析构函数?
有何用途?
答:
在C++-中不能声明虚构造函数.多态是不同的对象对同一消息有不同的行为特性.虚函数作为运行过程中多态的基础,主要是针对对象的,面构造函数是在对盘产生之前运行的,因此虚构造函数是没有童义的.
在C++中可以声明虚析构函数.析构函数的功能是在该类对象消亡之前进行一些必要的清理工作,如果一个类的析构函数是虚函数,那么,由它派生而来的所有子类的析构函数也是虚函数.析构函数设置为虚函数之后,在使用指针引用时可以动态联编,实理运行时的多态,保证使用基类的指针就能够谓用适当的析构函数指针对不同的对象进行清理工作.
10.声明一个Shape抽象类,在此基础上派生出Rectangle和Circle类,二者都有GetArea()函数计算对象的面积,GetPerim()函数计算对象的周长。
解答:
#include〈iostream.h〉
#include〈math。
h>
classshape
{public:
virtualvoidgetarea()=0;
virtualvoidgetperim()=0;
};
classrectangle:
publicshape
{ inta,b,c;
doubles,p;
public:
rectangle(inta1,intb1,intc1) {a=a1;b=b1;c=c1;}
voidgetperim()
{ p=a+b+c;cout〈〈"周长”〈〈p< voidgetarea()
{ p=(a+b+c)/2.0;
s=sqrt(p*(p—a)*(p—b)*(p—c));
cout<<"面积 "〈
}
};
classcircle:
publicshape
{ floatr,s,p;
public:
circle(floatr1) {r=r1;}
voidgetperim() { p=2*r*3.1415926;cout〈〈”周长”<
voidgetarea() { s=r*r*3。
1415926; cout〈〈”面积 "<
};
voidshow(shape*p)
{p—〉getarea();
p-〉getperim();
}
voidmain()
{shape*p;
rectanglea(3,4,5);
circle b(10);
p=&a; show(p);
p=&b; show(p);
}
10.4 补充习题
(6)有如下类的定义。
空格处的语句是( ).
classMyClass
{public:
MyClass(inta=0,intb=0){ X=a;Y=b; }
voidChange()const {X—=10; Y+=10; }
private:
( ) intX,Y;
};
A. static B. const C. mutable D. 不需要填入内容
(7)编译时的多态性可以通过使用( )获得。
A.虚函数和指针B.重载函数和析构函数 C.虚函数和对象 D.虚函数和引用
2.填空
(1).单目运算符作为类成员函数重载时 形参;双目运算符作为 重载时需声明其右操作数,作为 重载时需声明全部操作数.
10。
根据给定的程序执行结果,将下列程序补充完整。
#include〈iostream.h>
classBase
{public:
Base(inti){b=i;}
(1)
protected:
intb;
};
classDerive1:
publicBase
{public:
(2)
voidPrint(){cout<<"Derive1’sPrint()called。
"<〈endl;}
};
classDerive2:
publicBase
{ (3)
};
voidfun( (4) ){ obj->Print();}
voidmain()
{ (5)
fun(d1);
fun(d2);
}
程序的执行结果如下:
Derive1’sPrint()called.
Derive2'sPrint()called.
#includeclassBase
{public:
Base(inti){b=i;}
virtualvoidPrint(){};
protected:
intb;
};
classDerive1:
publicBase
{public:
Derive1():
Base
(1){};
voidPrint(){cout〈〈"Derive1’sPrint()called."<};
classDerive2:
publicBase
{public:
Derive2():
Base
(1){};
voidPrint(){cout<<”Derive2'sPrint()called。
"<〈endl;}
};
voidfun(Base*obj){obj—>Print();}
voidmain()
{Base*d1=newDerive1;
Base*d2=newDerive2;
fun(d1);
fun(d2);
}