C++虚函数相关练习及答案分析
c++多态性与虚函数习题答案

多态性与虚函数1.概念填空题1.1 C++支持两种多态性,分别是编译时和运行时。
1.2在编译时就确定的函数调用称为静态联编,它通过使用函数重载,模板等实现。
1.3在运行时才确定的函数调用称为动态联编,它通过虚函数来实现。
1.4虚函数的声明方法是在函数原型前加上关键字virtual。
在基类中含有虚函数,在派生类中的函数没有显式写出virtual关键字,系统依据以下规则判断派生类的这个函数是否是虚函数:该函数是否和基类的虚函数同名;是否与基类的虚函数参数个数相同、类型;是否与基类的虚函数相同返回类型。
如果满足上述3个条件,派生类的函数就是虚函数。
并且该函数覆盖基类的虚函数。
1.5 纯虚函数是一种特别的虚函数,它没有函数的函数体部分,也没有为函数的功能提供实现的代码,它的实现版本必须由派生类给出,因此纯虚函数不能是友元函数。
拥有纯虚函数的类就是抽象类类,这种类不能实例化。
如果纯虚函数没有被重载,则派生类将继承此纯虚函数,即该派生类也是抽象。
3.选择题3.1在C++中,要实现动态联编,必须使用(D)调用虚函数。
A.类名B.派生类指针C.对象名D.基类指针3.2下列函数中,不能说明为虚函数的是(C)。
A.私有成员函数B.公有成员函数C.构造函数D.析构函数3.3在派生类中,重载一个虚函数时,要求函数名、参数的个数、参数的类型、参数的顺序和函数的返回值(A)。
A.相同B.不同C.相容D.部分相同3.4当一个类的某个函数被说明为virtual时,该函数在该类的所有派生类中(A)。
A.都是虚函数B.只有被重新说明时才是虚函数C.只有被重新说明为virtual时才是虚函数D.都不是虚函数3.5(C)是一个在基类中说明的虚函数,它在该基类中没有定义,但要求任何派生类都必须定义自己的版本。
A.虚析构函数B.虚构造函数C.纯虚函数D.静态成员函数3.6 以下基类中的成员函数,哪个表示纯虚函数(C)。
A.virtual void vf(int);B.void vf(int)=0;C.virtual void vf( )=0;D.virtual void vf(int){ }3.7下列描述中,(D)是抽象类的特性。
习题9及其解答

习题9及其解答9.1 选择题1.在C++中,要实现动态联编,必须使用( d )调用虚函数。
(a) 类名(b) 派生类指针(c) 对象名(d) 基类指针2.下列函数中,不能说明为虚函数的是( c )。
(a) 私有成员函数(b) 公有成员函数(c) 构造函数(d) 析构函数3.在派生类中,重载一个虚函数时,要求函数名、参数的个数、参数的类型、参数的顺序和函数的返回值( a )。
(a) 相同(b) 不同(c) 相容(d) 部分相同4.C++中,根据( d )识别类层次中不同类定义的虚函数版本。
(a) 参数个数(b) 参数类型(c) 函数名(d) this指针类型5.虚析构函数的作用是( c )。
(a) 虚基类必须定义虚析构函数(b) 类对象作用域结束时释放资源(c) delete动态对象时释放资源(d) 无意义6.下面函数原型中,( b )声明了fun为纯虚函数。
(a) void fun()=0; (b) virtual void fun()=0;(c) virtual void fun(); (d) virtual void fun(){ };7.若一个类中含有纯虚函数,则该类称为( c )。
(a) 基类(b) 纯基类(c) 抽象类(d) 派生类8.假设 Aclass为抽象类,下列正确的说明语句是( b )。
(a) Aclass fun( int ) ; (b) Aclass * p ;(c) int fun( Aclass ) ; (d) Aclass Obj ;9.下面描述中,正确的是( d )。
(a) 虚函数是没有实现的函数(b) 纯虚函数是返回值等于0的函数(c) 抽象类是只有纯虚函数的类(d) 抽象类指针可以指向不同的派生类10.构造异质链表的意义是( d )。
(a) 用数组组织类对象(b) 用链表组织类对象(c) 用抽象类指针指向派生类对象(d) 用抽象类指针构造派生类对象链表9.2阅读下列程序,写出执行结果1.#include <iostream>using namespace std;class Bclass{ public:Bclass( int i, int j ) { x = i; y = j; }virtual int fun() { return 0 ; }protected:int x, y ;};class Iclass:public Bclass{ public :Iclass(int i, int j, int k):Bclass(i, j) { z = k; }int fun() { return ( x + y + z ) / 3; }private :int z ;};int main(){ Iclass obj( 2, 4, 10 );Bclass p1 = obj;cout << p1.fun() << endl;Bclass &p2 = obj ;cout << p2.fun() << endl;cout << p2.Bclass :: fun() << endl;Bclass *p3 = &obj;cout << p3 -> fun() << endl;}【解答】552.#include <iostream>using namespace std;class Base{ public:virtual void getxy( int i,int j = 0 ) { x = i; y = j; } virtual void fun() = 0 ;protected:int x , y;} ;class A : public Base{ public:void fun(){ cout<<"x = "<<x<<'\t'<<"y = x * x = "<<x*x<<endl; }};class B : public Base{ public:void fun(){ cout << "x = " << x << '\t' << "y = " << y << endl;cout << "y = x / y = " << x / y << endl;}} ;int main(){ Base * pb;A obj1;B obj2;pb = &obj1;pb -> getxy( 10 );pb -> fun();pb = &obj2;pb -> getxy( 100, 20 );pb -> fun();}【解答】x = 10 y = x*x = 100x = 100 y = 20y = x / y = 59.3 思考题1.在C++中,使用类体系依靠什么机制实现程序运行时的多态?【解答】在C++中,基类指针可以指向派生类对象,以及基类中拥有虚函数,是支持多态性的前提。
二级C++笔试353_真题(含答案与解析)-交互

二级C++笔试353(总分100, 做题时间90分钟)一、选择题下列各题A) 、B) 、C) 、D) 四个选项中,只有一个选项是正确的。
1.静态成员函数不能说明为SSS_SINGLE_SELA 整型函数B 常函数C 虚函数D 内联函数分值: 2答案:C[解析] 静态函数不能说明为虚函数。
2.以下程序的输出结果为main()int m=7,n=4;float a=38.4,b=6.4,x;x=m/2+n*a/b+1/2;cout<<x<<end1;}SSS_SINGLE_SELA 27.000000B 27.500000C 28.000000D 28.500000分值: 2答案:A[解析] 本题考查表达式值的类型由参与运算的所有变量的类型中优先级最高的变量类型所决定。
不过要注意的是整型向float型转换时.将丢失小数部分,即向下驭值。
3.关于虚函数的描述中正确的是SSS_SINGLE_SELA 虚函数是一个静态成员函数B 虚函数是一个非成员函数C 虚函数既可以在函数说明时定义,也可以在函数实现时定又D 派生类的虚函数与基类中对应的虚函数具有相同的参数个数和类型分值: 2答案:D[解析] 虚函数不能定义为静态函数;虚函数的作用在于继承,表现出动态性。
所以,在派生类中定义的虚函数必须和基类中对应的虚函数具有相同的参数个数和类型。
4.若有说明:int a [3][4];则对a数组元素的非法引用是SSS_SINGLE_SELA a[0][2*1]B a[1][3]C a[4-2][0]D a[0][4]分值: 2答案:D[解析] 在数组这部分的知识里面,数组下标越界是一个比较容易忽略的问题,其下标是从。
开始,至n-1为止,因此选项D是正确答案。
5.静态成员函数没有SSS_SINGLE_SELA 返回值B this指针C 指针参数D 返回类型分值: 2答案:B[解析] this指针是系统隐含的用于指向当前对象的指针。
C++二级试题选择题练习(带注解,答案)

1.以下运算符函数中肯定不属于类FunNumber的成员函数的是__D____。
本题考查的是类的成员函数。
选项A是重载了负号或减法运算符,由于减法运算符它具有两个操作数,而题面原型中只有一个,如果重载的是减号运算符,则必为成员函数。
选项B中由于没参数,无论是负号或减法运算符至少具有一个参数,所以它必为成员函数,同时也必定是重载了负号运算符。
选项C是必定以成函数的方式重载,因为C++规定不能对内置类的运算符进行重载,所以它不可能是友元函数(因为操作数为内置的int型),所以必为成员函数重载,且必定是重载了减法运算符。
选项D有两个参数,无论是负号或减法运算符,其操作数不超2个,所以必定为友元函数重载,且重载了减法运算符。
故本题答案为D。
2.运算符重载是对已有的运算符赋予多重含义,因此__C____。
本题主要考查了运算符重载。
C++在重载运算符时,必须符合下面的条件:1、不能重载内置C++数据类型(如int,double等类型)的运算符的含义;2、不能定义C++中没有的运算符;3、不能改变重载运算符的优先级与操作数的个数;4、有些运算符不能被重载,如域运算符(::),条件运算符(?:)等,具体哪些运算符不能被重载与编译器有关。
3.有如下程序:#include <iostream>using namespace std;class Complex{double re,im;public:Complex (double r,double i):re(r),im(i) { }double real() const {return re;}double image() const { return im;}Complex& operator+=(Complex a){re+=a.re ;im+=a.im ;return *this ;}};ostream& operator<<(ostream& s,const Complex& z){return s<<'('<<z.real()<<','<<z.image()<<')';}int main(){Complex x(1,-2),y(2,3);cout<<(x+=y) <<endl;return 0;}执行这个程序的输出结果是_(3,1)_____。
C 程序设计与应用基础第五章 多态性习题答案

根据结果将程序补充完整。
#incude <iostream.h>
class Base
{
public:
Base(){cout<<"Base's cons."<<endl;}
___varitual ~Base()___{cout<<"Base's des."<endl;}
};
class Derived:public Base
第五章多态性
1、填空题
1)在一个成员函数内调用一个虚函数时,对该虚函数的调用进行___动态______联编。
2)动态联编是在__虚函数___的支持下实现的,它通过___指针和引用__来调用该函数操作。
3)下列程序的运行结果如下:
Base's cons.
Derived's cons.
Derived's des.
salesman s1;
employee *emp[4]={&m1,&t1,&sm1,&s1};
int i;
for(i=0;i<4;i++)
{
emp[i]->promote();
emp[i]->pay();
emp[i]->display();
}
}
2)编写一个程序,建立两种类型的表:队列与堆钱,使它们可以共用一个接口访问。
答案:
#include <iostream.h>
#include <string.h>
class employee
C++(练习)第9章,多态性与虚函数

B虚函数
C派生类
D其他都不对
参考答案
A
5.关于虚函数的描述中,()是正确的。
A虚函数是一个静态成员函数
B虚函数是一个非成员函数
C虚函数既可以在函数说明时定义,也可以在函数实现时定义
D派生类的虚函数与基类中对应的虚函数具有相同的参数个数和类型
参考答案
D
6.下面4个选项中,()是用来声明虚函数的。
C virtual void tt(int);
D virtual void tt(int){ };
参考答案
A
二.填空题
1.如果类包含了一个或多个__1__,则它是抽象类。
参考答案
1:纯虚函数
2.虚函数必须是类的__1__。
参考答案
1:非静态成员函数或成员函数
3.多态性分为两类:编译时的多态性和__1__的多态性。
参考答案
1:友元函数
7.如果在类中定义了一个成员函数为__1__,则表明在该继承层次链条的派生类中有可能重新定义这个成员函数的实现,即它可能被派生类的同名函数所覆盖。
参考答案
1:虚函数
8.动态多态性通过__1__实现。
参考答案
1:虚函数
9.定义一个函数名为fun,返回值为int,没有参数的纯虚函数的定义是__1__。
参考答案
1:引用或指针
20.含有纯虚函数的类称为__1__。
参考答案
1:抽象类
21.在C++中,编译时的多态性是通过函数重载和__1__体现的。
参考答案
1:模板
三.问答题
四.编程题
参考答案
1:纯虚函数
12.虚函数必须是类的__1__。
实验七 虚函数及应用

实验七虚函数及应用一、实验目的1.理解虚函数与运行时(动态)多态性之间的关系,掌握虚函数的定义及应用;2.理解纯虚函数与抽象类的概念,掌握抽象类的定义及应用;3.理解虚析构函数的概念及作用。
二、实验学时课内实验:2课时课外练习:2课时三本实验涉及的新知识㈠虚函数与动态多态性在C++中,如果将基类与派生类的同名成员函数定义为虚函数,就可以定义一个基类指针,当基类指针指向基类对象时访问基类的成员函数,当基类指针指向派生类对象时访问派生类的成员函数,实现在运行时根据基类指针所指向的对象动态调用成员函数,实现动态多态性。
换句话说,虚函数与派生类相结合,使C++能支持运行时(动态)多态性,实现在基类中定义派生类所拥有的通用“接口”,而在派生类中定义具体的实现方法,即“一个接口,多种方法”。
㈡虚函数的定义1.在基类中定义在定义函数的前面加上“virtual ”。
即:virtual 返回类型函数名(参数表){ …… }2.在派生类中定义函数的返回类型、函数名、参数的个数、参数类型及顺序必须与基类中的原型完全相同。
3.说明:⑴在派生类中定义虚函数时,可用“virtual”也可不用“virtual”(最好都使用)。
⑵虚函数在派生类中重新定义时,其原型必须与基类中相同。
⑶必须用基类指针访问虚函数才能实现运行时(动态)多态性;当用普通成员函数的调用方法(即用圆点运算符)调用虚函数时,为静态调用;⑷虚函数在自身类中必须声明为成员函数(不能为友元函数或静态成员函数),但在另一个类中可以声明为友元函数。
⑸虚函数可以公有继承多次,其虚函数的特性不变。
⑹构造函数不能定义为虚函数,但析构函数可以定义为虚函数。
⑺虚函数与重载函数的关系①普通函数重载是通过参数类型或参数的个数不同实现的;重载一个虚函数时,其函数原型(返回类型、参数个数、类型及顺序)完全相同。
②当重载的虚函数只有返回类型不同时,系统将给出错误信息;如果定义的虚函数只有函数名相同,而参数个数或类型不同时,则为普通函数重载。
国家二级(C++)笔试模拟试卷100(题后含答案及解析)

国家二级(C++)笔试模拟试卷100(题后含答案及解析)题型有:1. 选择题 2. 填空题选择题(每小题2分,共70分)下列各题A、B、C、D四个选项中,只有一个选项是正确的,请将正确选项涂写在答题卡相应位置上。
1.以下哪个特征不是面向对象思想中的主要特征( )。
A.多态B.继承C.封装D.垃圾回收正确答案:D2.下面关于虚函数的描述中,正确的是( )。
A.虚函数是一个静态成员函数B.虚函数是一个非成员函数C.虚函数既可以在函数说明时定义,也可以函数实现时定义D.派生类的虚函数与基类中对应的虚函数具有相同的参数个数和类型正确答案:D3.有关构造函数的说法不正确的是( )。
A.构造函数名字和类的名字一样B.构造函数在说明类变量时自动执行C.构造函数无任何函数类型D.构造函数有且只有一个正确答案:D4.对于常数据成员,下面描述正确的是()。
A.常数据成员可以不初始化,并且不能更新B.常数据成员必须被初始化,并且不能更新C.常数据成员可以不初始化,并且可以被更新D.常数据成员必须被初始化,并且可以被更新正确答案:B5.下列描述中错误的是( )。
A.派生类可以作为基类派生其他的子类B.派生类继承基类的所有数据成员C.派生类可以有多个基类D.派生类不能继承一些函数成员正确答案:B6.实现输出为八进制的符号是( )。
A.decB.hexC.octD.setw(8)正确答案:C7.派生类的对象对它的基类成员中( ),是可以访问的。
A.公有继承的公有成员B.公有继承的私有成员C.公有继承的保护成员D.私有继承的公有成员正确答案:A8.下列说法中错误的是( )。
A.公有继承时基类中的public成员在派生类中仍是public的B.公有继承时基类中的private成员在派生类中仍是private的C.私有继承时基类中的public成员在派生类中是private的D.保护继承时基类中的public成员在派生类中是protected的正确答案:B9.有如下程序段&include<iostream.h>void main( ) {int a=14,b=15,x;char c=‘A’:x=(a && b) && (c<’B’=;cout<<x;= 执行该程序段后,x的值为A.tureB.FALSEC.0D.1正确答案:D10.若有说明:int [3][4]={0};则下面叙述正确的( )。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
代码:
#include <iostream>
using namespace std;
class A
{
public:
A(){cout<<"调用A的构造函数"<<endl;A::func();}
virtual void func(){cout<<"A::func()"<<endl;}
~A(){cout<<"调用A的析构函数"<<endl;}
};
class D
{
public:
D(){cout<<"调用D的构造函数"<<endl;}
void func(){cout<<"D::func()"<<endl;}
~D(){cout<<"调用D的析构函数"<<endl;}
};
class B:public A
};
class B:public A
{
public:
B(){cout<<"调用B的构造函数"<<endl;B::func();}
void func(){cout<<"B::func()"<<endl;}
~B(){cout<<"调用B的析构函数"<<endl;}
D d;
};
class C:public B
~A(){cout<<"调用A的析构函数"<<endl;}
};
class D
{
public:
D(){cout<<"调用D的构造函数"<<endl;}
~D(){cout<<"调用D的析构函数"<<endl;}
};
class B:public A
{
public:
D d;
B(){cout<<"调用B的构造函数"<<endl;}
~B(){cout<<"调用B的析构函数"<<endl;}
};
int main(void)
{
A *p =new B;
delete p;
return 0;
}
运行结果:
将A的析构函数不设置为虚析构函数时的代码:
#include <iostream>using namespac std;class A
{
1、A,B,C,D四个类,分别是B继承于A,C继承于B,其中B类中内嵌一D对象,
在main函数中构造一C对象,观测构造函数和析构函数的调用顺序。
代码:
#include <iostream>
using namespace std;
class A
{
public:
A(){cout<<"调用A的构造函数"<<endl;}
{
public:
C(){cout<<"调用C的构造函数"<<endl;C::func();}
void func(){cout<<"C::func()"<<endl;}
~C(){cout<<"调用C的析构函数"<<endl;}
};
int main(void)
{
C c;
return 0;
}运行结果:
结果分析:
using namespace std;
class A
{
public:
A(){cout<<"调用A的构造函数"<<endl;}
virtual ~A(){cout<<"调用A的虚析构函数"<<endl;}
};
class B:public A
{
public:
B(){cout<<"调用B的构造函数"<<endl;}
在主函数中创建一个C的对象,分别调用A、B、C的构造函数,基类和派生类中都调用了自己的func()函数。
4、有类A,派生出类B,有如下代码
A *p = new B;
delete p;
观察并分析将A的析构函数设置或不设置为虚析构函数的表现。
将A的析构函数设置为虚析构函数时的代码:
#include <iostream>
构造类C的对象时,因为C继承于B,B继承于A,且在B类中内嵌了D的对象,所以创建C的对象时,先调用A的构造函数,然后再调用内嵌对象d的构造函数,然后调用B的构造函数,然后调用C的构造函数,然后依次反向调用析构函数。当类之间存在继承关系时,创建对象时总是从最远(最里层)的类开始创建。
2、给上题A类增加一虚函数func,并要求B/C派生类也提供该函数实现,并实验分别以指针、引用
cout<<"------------指针对象方式访问----------------"<<endl;
A *aa = new C;
aa->func();
cout<<"------------引用对象方式访问----------------"<<endl;
A &aaa = c;
aaa.func();
return 0;
public:
A(){cout<<"调用A的构造函数"<<endl;}
~A(){cout<<"调用A的析构函数"<<endl;}
};
class B:public A
{
public:
B(){cout<<"调用B的构造函数"<<endl;}
~B(){cout<<"调用B的析构函数"<<endl;}
};
int main(void)
void func(){cout<<"C::func()"<<endl;}
~C(){cout<<"调用C的析构函数"<<endl;}
};
int main(void)
{
C c;
cout<<"------------普通对象方式访问----------------"<<endl;
A a = c;
a.func();
{
A *p =new B;
delete p;
return 0;
}
运行结果:
结果分析:
当一个类作为基类时,应该将其析构函数声明为虚析构函数,这样做的目的是为了当基类的一个指针指向派生类的对象时,派生类的析构函数会被调用。
~B(){cout<<"调用B的析构函数"<<endl;}
};
class C:public B
{
public:
C(){cout<<"调用C的构造函数"<<endl;}
~C(){cout<<"调用C的析构函数"<<endl;}
};
int main(void)
{
C c;
return 0;
}
运行结果:
结果分析:
和普通对象方式访问该虚函数时的输出,并分析原因。
代码:
#include <iostream>
using namespace std;
class A
{
public:
A(){cout<<"调用A的构造函数"<<endl;}
virtual void func(){cout<<"A::func()"<<endl;}
~A(){cout<<"调用A的析构函数"<<endl;}
};
class D
{
public:
D(){cout<<"调用D的构造函数"<<endl;D::func();}
void func(){cout<<"D::func()"<<endl;}
~D(){cout<<"调用D的析构函数"<<endl;}
}
运行结果:
结果分析:
在主函数中创建A的对象,虽然A a = c,但是a是基类的对象,没有指向或者引用子类,所以当a调用func时,调用的是类A中的虚函数;而aa和aaa分别指向和引用了C的对象,所以其调用的是类C中的虚函数func(),而不是基类中的func()
3、给上题A类增加一虚函数func,并要求B/C派生类也提供该函数实现,并实验在不同类的构造函数、析构中
{
public:
B(){cout<<"调用B的构造函数"<<endl;}
void func(){cout<<"B::func()"<<endl;}