一、填空题
(1)C++的两种联编方式为:动态联编和静态联编。
(2)C++支持两种多态性,静态联编所支持的多态性被称为编译时的多态性、动态联编所支持的多态性被称为运行时的多态性。
(3)重载函数在编译时表现出多态性,是静态联编;而虚函数则在运行时表现出多态性是动态联编。
(4)为了区分重载函数,把一个派生类中重定义基类的虚函数称为覆盖。
(5)如果派生类与基类的虚函数仅仅返回类型不同,其余相同,则c++认为是使用了不恰当的虚函数。
(6)在构造函数和析构函数中调用虚函数时,采用静态联编。
(7)纯函数的定义是在虚函数定义的基础上,再让函数等于0 。
(8)对于包含有纯虚函数的类被称为抽象类。
二、选择题(至少选一个,可以多选)
(1)用关键字(A)标记的函数被称为虚函数。
A.virtual B.private C.public D.protected
(2)在C++中,要实现动态联编,必须使用(D)调用虚函数。
A.类名 B.派生类指针 C.对象名 D.基类指针
(3)下列函数中,可以作为虚函数的是(BD)。
A.普通函数 B.非静态成员函数 C.构造函数 D.析构函数
(4)在派生类中,重载一个虚函数时,要求函数名、参数的个数、参数的类型、参数的顺序和函数的返回值(B)。
A.不同 B.相同 C.相容 D.部分相同
(5)使用虚函数保证了在通过一个基类类型的指针(含引用)调用一个虚函数时,c++系统对该调用进行(A),但是,在通过一个对象访问一个虚函数,使用(B)。
A.动态联编 B.静态联编 C.动态编译 D.静态编译
(6)下面函数原型声明中,(C)声明的fun()为纯虚函数。
A.void func()=0; B.virtual void func()=0;
B.virtual void func(); C.virtual void func(){};
(7)若一个类中含有纯虚函数,则该类称为(C)。
A.基类 B.虚基类 C.抽象类 D.派生类
(8)假设Myclass为抽象类,下列声明(CD)是错误的。
A.Myclass& func(int); B.Myclass * pp;
C.int func(Myclass); D.Myclass Obj;
(9)下面描述中,(BD)是正确的。
A.虚函数是没有实现的函数 B.纯虚函数的实现是在派生类中定义
C.抽象类是只有纯虚函数的类 D.抽象类指针可以指向不同的派生类
三、判断题
(1)抽象类中只能由一个纯虚函数。 (×)
(2)构造函数和析构函数都不能说明为虚函数。 (×)
(3)程序中可以说明抽象类的指针或引用。 (√)
(4)一个类中的虚函数说明不仅对基类中的同名函数有影响,而且对它的派生类中重定义的函数也有影响。 (×)
(5)在构造函数和析构函数中调用虚函数时,采用动态联编,即它们所调动的虚函数是在派生类中重定义的虚函数。(×)
(6)因为没有为纯虚函数定义代码,所以在构造函数和析构函数内均不可调用纯虚函数。 (√)
四、 简答题
(1)什么叫做多态性?在c++中是如何实现多态的?
答:多态性就是同一个符号或名字在不同情况下具有不同解释的现象,即是指同一个函数的多种形态。C++可以支持两种多态性,编译时的多态性和运行时的多态性。多态性有两种表现形式:一种是不同的对象在收到相同的消息时,产生不同的动作,主要通过虚函数来实现;另一种是同一对象收到相同的消息却产生不同的函数调用,主要通过函数重载来实现。
(2)虚函数与一般重载函数有哪些区别?
答:虚函数与一般重载函数的区别,主要有以下几点:
1、重载函数只要求函数有相同的函数名,并且重载函数是在相同作用域中定义的名字相同的不同函数。而虚函数不仅要求函数名相同,而且要求函数的签名、返回类型也相同。也就是说函数原型必须完全相同,而且虚函数特性必须是体现在基类和派生类的类层次结构中。
2、重载函数可以是成员函数或友元函数,而虚函数只能是非静态成员函数。
3、构造函数可以重载,析构函数不能重载。正好相反,构造函数不能定义为虚函数,析构函数能定义为虚函数。
4、重载函数的调用是以所传递参数序列的差别作为调用不同函数的依据,而虚函数是根据对象的不同去调用不同类的虚函数。
5、重载函数在编译时表现出多态性,是静态联编;而虚函数则在运行时表现出多态性是动态联编,因此说动态联编是C++的精髓。
(3)什么叫做抽象类?抽象类有何作用?抽象类的派生类是否一定要给出纯虚函数的实现?
答:抽象类用来描述一组子类的共同的操作接口,它用作基类。从一个抽象类派生的类必须覆盖纯虚函数,或在该派生类中仍将它说明为纯虚函数,否则编译器将给出错误信息。说明了纯虚函数的派生类仍是抽象类。如果派生类中覆盖了所有的虚函数,则该派生类不再是抽象类。
(4)能否声明虚析构函数?有何用途?
答:能声明。如果一个类的析构函数是虚函数,那么,由它派生而来的所有子类的析构函数也是虚函数。如果析构函数为虚函数,则这个调用采用动态联编。delete运算符和析构函数一起工作,当使用delete删除一个对象时,delete隐含着对析构函数的一次调用,这样保证了使用基类类型的指针能够调用适当的析构函数针对不同的对象进行清除工作。
五、程序设计题
(1)使用虚函数编写程序求球体和圆柱体的体积及表面积。由于球体和圆柱体都可以看作由圆继承而来,所以可以定义圆类Circle作为基类。在Circle类中定义一个数据成员radius和两个虚函数area()和volume()。由Circle类派生Sphere类和Column类。在派生类中对虚函数area()和volume()重新定义,分别求球体和圆柱体的体积及表面积。
- #include <iostream>
- #include <iomanip>
- using std::fixed;
- using std::setprecision;
- using namespace std;