虚函数与多态性(110526)_练习题
多态与虚函数 例题
题目:水果类与虚函数多态与虚函数例题1.题目内容与要求①首先设计一个水果类(Fruit)作为基类,成员函数为显示“水果”函数;②然后设计Fruit类的四个派生类:香蕉类(Banana)、苹果类(Apple)、梨子类(Pear)和桃子类(Peach),成员函数分别为显示“香蕉”、“苹果”、“梨子”和“桃子”函数;③最后在主函数中定义这些类的对象,并调用它们的显示函数。
2.类的分析主函数水果类对象 香蕉类对象 苹果类对象 梨子类对象 桃子类对象 显示函数调用水果类显示函数香蕉类显示函数苹果类显示函数梨子类显示函数桃子类显示函数3.类的设计mainFruit f; Banana b; Apple a; Pear p; Peach ph; f=b; f.print(); f=a; f.print(); ……FruitprintBananaprintAppleprintPearprintPeachprint4.基类程序代码// 基类: 水果类class Fruit{public:void print() {cout<< "水果" <<endl; }};// 派生类1: 香蕉类class Banana: public Fruit{ public:void print() {cout<< "香蕉" <<endl;} };// 派生类2: 苹果类class Apple: public Fruit{ public:void print() {cout<< "苹果" <<endl;} };派生类程序代码// 派生类3: 梨子类class Pear: public Fruit{ public:void print() { cout<< "梨子" <<endl;} };// 派生类4: 桃子类class Peach: public Fruit{ public:void print() { cout<< "桃子" <<endl;} };#include <iostream> using namespace std; <5个类的定义在此!>int main() // 主函数 {核心代码在此!return 0; }主函数程序代码Fruit * pFruit[] = { new Fruit(),new Banana(), new Apple(), new Pear(), new Peach() };for(int i = 0; i < 5; i++) { (*pFruit[i]).print(); }❝从以上5行运行结果来看,似乎调用的都是基类的print 函数。
多态练习题
1、生成表示学生的类XS,提供成员函数dispXM()、dispXB()和dispNL()分别用来显示姓名、性别和年龄,并将他们全部定义为纯虚函数;生成CZS类表示初中生,包含数据成员xm、xb和nl表示学生的姓名、性别和年龄,提供成员函数dispXM()、dispXB()和dispNL()分别用来显示姓名、性别和年龄;再生成类GZS表示高中生和类DXS表示大学生,同样包含相同含义的数据成员xm、xb和nl,也包括成员函数dispXM()、dispXB()和dispNL()。
要求:(1)设计和实现基本类XS(2)设计和实现派生类CZS,GZS和DXS(3)分别生成CZS、GZS、DXS类对象(4)将CZS、GZS、DXS类对象的指针赋给指针赋给XS类的指针变量。
(5)分别用XS类的指针和引用访问dispXM()、dispXB()和dispNL()函数。
(6)观察程序结果。
#include <iostream>#include <string.h>using namespace std;class XS{public:virtual void dispXM()=0;virtual void dispXB()=0;virtual void dispNL()=0;};class CZS:public XS{public:CZS(char * m="张三",int b=1,int n=14);void dispXM();void dispXB();void dispNL();protected:char xm[9];int xb,nl;};CZS::CZS(char *m,int b,int n){strcpy(xm,m);xb=b,nl=n;}void CZS::dispXM(){cout<<"name:"<<xm<<endl;}void CZS::dispXB(){if(xb==1)cout<<"Man"<<endl;if(xb==0)cout<<"Woman"<<endl;}void CZS::dispNL(){cout<<"age:"<<nl<<endl;}class GZS:public XS{public:GZS(char * m="张三",int b=1,int n=17);void dispXM();void dispXB();void dispNL();protected:char xm[9];int xb,nl;};GZS::GZS(char *m,int b,int n){strcpy(xm,m);xb=b,nl=n;}void GZS::dispXM(){cout<<"name:"<<xm<<endl;}void GZS::dispXB(){if(xb==1)cout<<"Man"<<endl;if(xb==0)cout<<"Woman"<<endl;}void GZS::dispNL(){cout<<"age:"<<nl<<endl;}class DXS:public XS{public:DXS(char * m="张三",int b=1,int n=20);void dispXM();void dispXB();void dispNL();protected:char xm[9];int xb,nl;};DXS::DXS(char *m,int b,int n){strcpy(xm,m);xb=b,nl=n;}void DXS::dispXM(){cout<<"name:"<<xm<<endl;}void DXS::dispXB(){if(xb==1)cout<<"Man"<<endl;if(xb==0)cout<<"Woman"<<endl; }void DXS::dispNL(){cout<<"age:"<<nl<<endl;}void displayP(XS *p){p->dispXM();p->dispXB();p->dispNL();}void displayR( XS &p){p.dispXM();p.dispXB();p.dispNL();}void main(){CZS czs("赵一",1,12);GZS gzs("钱二",0,15);DXS dxs("孙三",1,18);XS *p;//定义抽象基类的指针变量pp=&czs;//将初中生对象czs的地址赋给pdisplayP(p);p=&gzs;//将高中生对象czs的地址赋给pdisplayP(p);p=&dxs;//将大学生对象czs的地址赋给pdisplayP(p);cout<<"\n----------------------------------------\n";XS &r1=czs;//定义抽象基类的引用变量r1为czs的别名displayR(r1);XS &r2=gzs;//定义抽象基类的引用变量r2为czs的别名displayR(r2);XS &r3=dxs;//定义抽象基类的引用变量r3为czs的别名displayR(r3);cout<<"\n----------------------------------------\n";}2、某小型公司主要有3类人员:经理、兼职技术人员、兼职销售员。
复习题及答案2
一、选择题下列各题A)、B)、C)、D)四个选项中,只有一个选项是正确的。
请将正确选项涂写在答题卡相应位置上,答在试卷上不得分。
(4)下面选项中不属于面向对象程序设计特征的是。
A)继承性B)多态性C)类比性D)封装性(11)为了取代C中带参数的宏,在C++中使用A)重载函数B)内联函数C)递归函数D)友元函数(12)下列关于类定义的说法中,正确的是A)类定义中包括数据成员和函数成员的声明B)类成员的缺省访问权限是保护的C)数据成员必须被声明为私有的D)成员函数只能在类体外进行定义(13)下列关于派生类构造函数和析构函数的说法中,错误的是A)派生类的构造函数会隐含调用基类的构造函数B)如果基类中没有缺省构造函数,那么派生类必须定义构造函数C)在建立派生类对象时,先调用基类的构造函数,再调用派生类的构造函数D)在销毁派生类对象时,先调用基类的析构函数,再调用派生类的析构函数(14)通过运算符重载,可以改变运算符原有的A)操作数类型B)操作数个数C)优先级D)结合性(16)使用输入输出操作符setw,可以控制A)输出精度B)输出宽度C)对齐方式D)填充字符(17)下列字符串中,不可以用作C++标识符的是A)y_2006 B)____TEST__H C)Retum D)switch (18)字面常量42、4.2、42L的数据类型分别是A)long、double int B)long、float、int C)int、double、long D)int、float、long(19)执行下列语句段后,输出字符“*”的个数是for(int i =50;I>1;— i )cout<<”*”A)48 B)49C)50 D)51(20)有如下程序段int i =0, j=1;int &r=i ; // ①r =j; //②int *p=&i ; //③*p=&r ; //④基中会产生编译错误的语句是A)④B)③C)②D)①(21)有如下函数定义:void func (int a,int&b){a++; b++;}若执行代码段:int x=0 ,y=1func(x,y);则变量x和y值分别是A)0和1 B)1和1 C)0和2D)1和2 (22)有如下程序:#include <iostream>using namespace std;class A{public:static int a;void init(){a=1;}A(int a=2){init();a++;}};int A::a=0;A obj;int main(){cout<<A::a;return 0;} 运行时输出的结果是A)0 B)1 C)2 D)3(23)下列有关继承和派生的叙述中,正确的是A)派生类不能访问基类的保护成员B)作为虚基类的类不能被实例化C)派生类应当向基类的构造函数传递参数D)虚函数必须在派生类中重新实现(24)下列运算符中,不能被重载的是A)&&B)!= C).D)++ (26)在语句cin>>data;中,cin是A)C++的关键字B)类名C)对象名D)函数名(27)有如下程序:#include <iostream>using namespace std;class test {private:int a;public:test(){ cout<<"constructor"; }test(int a){ cout<<"constructor"; }test(const test&_test){ a=_test.a;cout<<"copy constructor";}~test(){cout<<"destructor";}};int main(){ test A(3);return 0; }运行时输出的结果是A)3 B)constructor destruclor C)copy constructor D)3 dstructor destruclor(28)若有如下类声明class My Class {public:MyClass(){cout<<1;}};执行下列语句MyClass a,b[2],*P[2];以后,程序的输出结果是A)11 B)111C)1111 D11111(29)有如下程序:#include <iostream>using namespace std;class point{public:static int number;public:point() { number++;} ~point() {number--;}};int point::number=0;void main(){ point *ptr;point A,B;{point *ptr_point=new point[3];ptr=ptr_point;}point C;cout<<point::number;delete[] ptr;}A)3 B)4 C)6D)7(30)如果不使用多态机制,那么通过基类的指针虽然可以指向派生类对象,但是只能访问从基类继承的成员,有如下程序,没有使用多态机制。
习题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 程序设计与应用基础第五章 多态性习题答案
根据结果将程序补充完整。
#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++虚函数相关练习及答案分析
代码:
#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;}
《Java程序设计案例教程》第十章练习答案
第10章多态性与虚函数一、单项选择题1.实现运行时的多态性要使用(D)。
A.重载函数B.构造函数C.析构函数D.虚函数2.通过运算符重载,可以改变运算符原有的(A)。
A.操作数类型B.操作数个数C.优先级D.结合性3.将运算符重载为类成员函数时,其参数表中没有参数,说明该运算符是(B)。
A.不合法的运算符B.一元运算符C.无操作数的运算符D.二元运算符4.在重载一个运算符时,其参数表中没有任何参数,说明该运算符是(B)。
A.作为友元函数重载的一元运算符B.作为成员函数重载的一元运算符C.作为友元函数重载的二元运算符D.作为成员函数重载的二元运算符5.如果表达式++a中的"++"是作为成员函数重载的运算符,若采用运算符函数调用格式,则可表示为(D)。
A.a.operator++(1)B.operator++(a)C.operator++(a,1)D.a.operator++()6.如果表达式a>=b中的">="是作为非成员函数重载的运算符,则可以等效地表示为(C)。
A.a.operator>=(b)B.b.operator>=(a)C.operator>=(a,b)D.perator>=(b,a)7.有如下程序:#include<iostream>using namespace std;class A{public:virtual void funl (){cout<<"A1";}void fun2 (){cout<<"A2";}};class B: public A{public:void funl (){cout<<"Bl";}void fun2 (){cout<<"B2";}};int main(){A*p=new B;p->funl ();p->fun2();return 0;}程序执行后,输出结果为(C)。
C++多态练习题
C++多态练习题⼀、填空题(1)C++的两种联编⽅式为:动态联编和静态联编。
(2)C++⽀持两种多态性,静态联编所⽀持的多态性被称为编译时的多态性、动态联编所⽀持的多态性被称为运⾏时的多态性。
(3)重载函数在编译时表现出多态性,是静态联编;⽽虚函数则在运⾏时表现出多态性是动态联编。
(4)为了区分重载函数,把⼀个派⽣类中重定义基类的虚函数称为覆盖。
(5)如果派⽣类与基类的虚函数仅仅返回类型不同,其余相同,则c++认为是使⽤了不恰当的虚函数。
(6)在构造函数和析构函数中调⽤虚函数时,采⽤静态联编。
(7)纯函数的定义是在虚函数定义的基础上,再让函数等于0 。
(8)对于包含有纯虚函数的类被称为抽象类。
⼆、选择题(⾄少选⼀个,可以多选)(1)⽤关键字(A)标记的函数被称为虚函数。
A.virtualB.privateC.publicD.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)是错误的。
c++多态性相关习题
多态性10.2 典型例题分析与解答例题1:指出下列对定义重载函数的要求中,哪些是错误的提法。
A.要求参数的个数不同。
B.要求参数中至少有一个类型不同。
C.求函数的返回值不同。
D. 要求参数的个数相同时,参数类型不同。
答案: C例题3:下面关于友元的描述中,错误的是()。
A. 友元函数可以访问该类的私有数据成员B. 一个类的友元类中的成员函数都是这个类的友元函数C. 友元可以提高程序的运行效率D. 类与类之间的友元关系可以继承答案:D1例题4:下述静态成员的特性中,()是错误的。
A. 静态成员函数不能利用this指针B. 静态数据成员要在类体外进行初始化C. 引用静态数据成员时,要在静态数据成员名前加<类名>和作用域运算符D. 静态数据成员不是所有对象所共有的答案:D例题5:关于虚函数的描述中,()是正确的。
A. 虚函数是一个静态成员函数B. 虚函数是一个非成员函数C. 虚函数既可以在函数说明时定义,也可以在函数实现时定义D. 派生类的虚函数与基类中对应的虚函数具有相同的参数个数和类型参考答案:D2例题11:分析下列程序的输出结果。
#include <iostream.h>class A{public:A() { cout<<"A's cons."<<endl; }virtual ~A() { cout<<"A's des."<<endl; }virtual void f() { cout<<"A's f()."<<endl; } void g() { f(); }};class B : public A{public:B() { f(); cout<<"B's cons."<<endl; }3~B() { cout<<"B's des."<<endl; }};class C : public B{public:C() { cout<<"C's cons."<<endl; }~C() { cout<<"C's des."<<endl; }void f() { cout<<"C's f()."<<endl; }};void main(){ A *a=new C;a->g();delete a;}4运行结果:A's cons.A's f().B's cons.C's cons.C's f().C's des.B's des.A's des.10.3 教材习题解答1.选择题(1)下列关于动态联编的描述中,错误的是()。
多态性例题
多态性1 知识要点1.多态性:多态是指同样的消息被不同类型的对象接收后导致完全不同的行为。
2.面向对象的多态性可以分为4类:重载多态、强制多态、包含多态和参数多态。
3.多态从实现的角度来讲可以划分为两类:编译时的多态和运行时的多态。
4.运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据导致不同类型的行为。
5.运算符重载的规则如下:1)C++语言中的运算符除了少数几个之外,全部可以重载,而且只能重载C++语言中已有的运算符。
2)重载之后运算符的优先级和结合性都不会改变。
3)运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。
一般来讲,重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。
不能重载的运算符只有5个,它们是类属关系运算符“.”、成员指针运算符“*”、作用域分辨符“::”、sizeof运算符和三目运算符“?:”。
前面两个运算符保证了C++语言中访问成员功能的含义不被改变。
作用域分辨符和sizeof运算符的操作数是类型,而不是普通的表达式,也不具备重载的特征。
6.运算符的重载形式有两种,重载为类的成员函数和重载为类的友元函数。
运算符重载为类的成员函数的一般语法形式为:函数类型 operater 运算符(形参表){ 函数体;}运算符重载为类的友元函数的一般语法形式为:friend 函数类型 operater 运算符(形参表){ 函数体;}7.虚函数说明虚函数的一般格式如下:virtual <函数返回类型说明符> <函数名>(<参数表>)在定义虚函数时要注意:(1) 虚函数是非静态的、非内联的成员函数,而不能是友元函数,但虚函数可以在另一个类中被声明为友元函数。
(2) 虚函数声明只能出现在类定义的函数原型声明中,而不能在成员函数的函数体实现的时候声明。
(3) 一个虚函数无论被公有继承多少次,它仍然保持其虚函数的特性。
虚函数部分习题
Class Mammal
{
Public:
(1)void Speak(){cout<<”This is a Mammal!”<<endl;}
};
Class Dog:public Mammal
{
Public:
void Speak(){cout<<”this is a Dog!”<<endl;}
{
B b,*pb=&b;
A a,*pa=&a;
void (A::*paf1)()=A::f1;
void (A::*paf2)()=A::f2;
void (B::*pbf1)()=B::f1;
void (B::*pbf2)()=B::f2;
(pa->*paf1)();
pa=&b;
(pa->*paf1)();
pa->print(); pb->print();
delete pa;
}
5.下列程序中声明一个Mammal类,再由此派生出Dog类,二者都定义Speak()成员函数,基类中定义Speak()为虚函数。主程序中分别声明一个Mammal类和Dog类的对象,再分别 用对象名.函数名和指针的形式调用Speak()函数。请填空完成程序,并上机运行验证。
{
protected:
int k;
public:
XX ( int n = 5 ) : k (n){ }
~XX ( )
{cout<<“XX”;}
virtual void f ( ) ;
};
void XX :: f ( )
最新《C++程序设计案例教程》习题答案第9章 多态性和虚函数的使用
第9章多态性和虚函数的使用一、选择题1.C. 2.C 3.A 4.C 5. 6.D二、程序题(略)三、简答题1.C++多态性主要体现在哪两个方面?答:在C++中,多态性是指系统调用同名的函数,实现不同的功能。
多态性包含静态多态性和动态多态性。
静态多态性体现在编译时函数重载或者运算符重载上;展现了同一类中多个同名函数的处理机制。
而动态多态性是指程序运行过程中通过虚函数动态地确定针对的对象,展现继承层次结构中同名函数的处理机制。
2. 比较函数重载和虚函数在概念上和使用方式有什么区别。
函数重载是指函数名称相同,但是参数的个数或者参数的数据类型不同。
因此,系统调用重载函数时,会依据参数确定调用哪一个。
而在继承的机制中,基类的成员函数可能会与派生类新增的成员函数同名,包括参数个数和参数类型,这种现象不属于函数重载。
当基类的一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。
派生类可以对虚函数重新定义。
虚函数实现动态多态的问题。
3.比较抽象类、虚函数、纯虚函数的概念和使用上的区别。
虚函数通常在基类中定义,定义可以是空,派生类中可以对虚函数重写,也可以不写。
虚函数起到了接口的默认行为作用。
纯虚函数在基类中是没有定义的,必须在直接或者间接派生类中加以实现,它起到了接口的作用。
包含了纯虚函数的类,被称为抽象类。
抽象类不能建立对象。
4.谈谈虚基类和虚函数,区分两者不同的概念和各自的作用。
在继承机制中,一个派生类继承多个直接基类,而这些基类又有一个公共的基类,这个公共的基类成员在继承中可能产生多个拷贝。
虚基类的基本原则是在内存中只有基类成员的一份拷贝。
这样,通过把基类继承声明为虚拟的,就只能继承基类的一份拷贝,从而消除歧义。
用virtual限定符把基类继承说明为虚拟的。
虚函数指基类中成员函数声明为 virtual ,使它在一个或多个派生类中被重新定义,虚函数的作用是实现多态性。
虚函数必须是基类的非静态成员函数,其访问权限可以protected或public。
c多态性与虚函数习题
1.1C++支持两种多态性,分别是静态和动态。
1.2在编译时就确定的函数调用称为静态联编,它通过使用重载函数实现。
1.3在运行时才确定的函数调用称为动态联编,它通过虚函数来实现。
1.4虚函数的声明方法是在函数原型前加上关键字virtual。在基类中含有虚函数,在派生类中的函数没有显式写出virtual关键字,系统依据以下规则判断派生类的这个函数是否是虚函数:该函数是否和基类的虚函数参数个数相同 /同名;是否与基类的虚函数相应类型相同;是否与基类的虚函数返回值类型相同。如果满足上述3个条件,派生类的函数就是虚函数。并且该函数覆盖基类的虚函数。
A.可以说明虚函数
B.可以进行构造函数重载
C.可以定义友元函数
D.不能定义其对象
3.8类B是类A的公有派生类,类A和类B中都定义了虚函数func( ),p是一个指向类A对象的指针,则p->A::func( )将()。
A.调用类A中的函数func( )
B.调用类B中的函数func( )
C.根据p所指的对象类型而确定调用类A中或类B中的函数func( )
using namespace std;
class A {
public:
virtual void func( ) {cout<<”func in class A”<<endl;}
};
class B{
public:
virtual void func( ) {cout<<”func in class B”<<endl;}
A.虚析构函数B.虚构造函数
C.纯虚函数D.静态成员函数
3.6以下基类中的成员函数,哪个表示纯虚函数(C)。
实验五运行时多态性一、基本练习填...
实验五:运行时多态性一、基本练习填空1.在一个派生类中重新定义基类的虚函数是______ __的另一种特殊形式,在派生类中重新定义此虚函数时,要求________ 、、、和都必须与基类中原型完全相同。
2.动态多态性是在程序运行时通过改变具有虚函数定义的基类使其指向不同派生类从而调用不同版本的动态地实现对同一的不同响应。
3.阅读以下程序后填空#include <iostream.h>class base{public:virtual void who() { cout<<"base class"<<endl; }};class derived1:public base{public:void who() { cout<<"derived1 class"<<endl; }};class derived2:public base{public:void who() { cout<<"derived2 class"<<endl; }};void main(){base obj1, *p;derived1 obj2;derived2 obj3;p=&obj1; p->who();p=&obj2; p->who();p=&obj3; p->who();}其运行结果:4.阅读以下程序后填空#include <iostream.h>class base{public:virtual void f1() { cout<<"f1 function of base"<<endl; }virtual void f2() { cout<<"f2 function of base"<<endl; }virtual void f3() { cout<<"f3 function of base"<<endl; }void f4() { cout<<"f4 function of base"<<endl; }};class derive:public base{public:void f1() { cout<<"f1 function of derive"<<endl; }void f2() { cout<<"f2 function of derive"<<endl; }void f4() { cout<<"f4 function of derive"<<endl; }};void main(){base obj1, *p;derive obj2;p=&obj1;p->f1(); p->f2(); p->f3();p=&obj2;p->f1(); p->f2(); p->f4();}其运行结果:5.阅读以下程序后填空#include <iostream.h>class base1{public:virtual void f1() { cout<<"f1 function of base1"<<endl; }void f2() { cout<<"f2 function of base1"<<endl; }void f3() { cout<<"f3 function of base1"<<endl; } };class base2{public:void f1() { cout<<"f1 function of base2"<<endl; }virtual void f2() { cout<<"f2 function of base2"<<endl; }void f3() { cout<<"f3 function of base2"<<endl; } };class derive:public base1,public base2{public:void f1() { cout<<"f1 function of derive"<<endl; }void f2() { cout<<"f2 function of derive"<<endl; }void f3() { cout<<"f3 function of derive"<<endl; } };void main(){base1 obj1, *p1;base2 *p2;derive obj2;p1=&obj1;p1->f1(); p1->f2(); p1->f3();p1=&obj2;p1->f1(); p1->f2(); p1->f3();p2=&obj2;p2->f1(); p2->f2(); p2->f3();}其运行结果:f1 function of base16.阅读以下程序后填空#include <iostream.h>class base{public:virtual void f1()=0;virtual void f2()=0;virtual void f3()=0;void f4() { cout<<"f4 function of base"<<endl; } };class derive:public base{public:void f1() { cout<<"f1 function of derive"<<endl; }void f2() { cout<<"f2 function of derive"<<endl; }void f3() { cout<<"f3 function of derive"<<endl; }void f4() { cout<<"f4 function of derive"<<endl; } };void main(){base *p;derive obj;p=&obj;p->f1(); p->f2(); p->f3(); p->f4();}其运行结果:7.阅读以下程序后填空#include <iostream.h>#include <string.h>class base{public:virtual void show()=0;virtual ~base() { cout<<"base::~base()"<<endl; } };class derive:public base{char *buf;public:derive(char *s){ buf=new char[strlen(s)+1]; strcpy(buf,s); }void show() { cout<<buf<<endl; }virtual ~derive(){ delete []buf; cout<<"derive::~derive()"<<endl; } };void fun(base* a) { delete a; }void main(){base *p=new derive("this is a derive object");p->show();fun(p);}其运行结果:8. 阅读以下程序后填空#include <iostream.h>class A{public:virtual ~A() { cout<<"调用A::~A()"<<endl; }};class B:public A{char *buf;public:B(int i) { buf=new char[i]; }virtual ~B(){delete [ ]buf;cout<<"调用B::~B()"<<endl;}};void fun(A *a) { delete a; }void main(){A *a=new B(10);fun(a);}程序的执行结果:选择1. 虚函数是用来,调用不同版本虚函数用以实现动态多态性。
c++练习题实验7 多态性和运算符重载.
employee *ptr[3]={&m1,&t1,&s1};
for(int i=0;i<3;i++)
ptr[i]->displayStatus();
}
1.完善【实例2】程序,写出实现以下功能的代码并上机调试。
(1)将成员函数displayStatus设置成虚函数,运行程序,观察运行结果。体会如何正确使用虚函数实现运行时的多态性。
根据题目要求,设计一个基类Employee,然后派生出Technician(兼职技术人员)类、Manager(经理)类和Salesman(兼职销售员)类。
#include <iostream.h>
#include <string>
using namespace std;
/////////////定义职员基类
{
hourlyRate=100; //每小时酬金100元
}
void technician::pay()
{
cout<<"输入本月工作时数:";cin>>workHours;
sumPay=hourlyRate*workHours;//月薪=工作小时*每小时酬金
}
void technician::displayStatus()
Y1 b(3,4),*bp=&b;
Z1 c(5,6),*cp=&c;
X1 *p[2]={&b,&c};
for(int i=0;i<2;i++)
p[i]->output();
资料:Part7-多态与虚函数-KEY
多态与虚函数单选题1.下面描述中,正确的是()。
A. virtual可以用来声明虚函数B. 含有纯虚函数的类是不可以用来创建对象的,因为它是虚基类C. 即使基类的构造函数没有参数,派生类也必须建立构造函数D. 静态数据成员可以通过成员初始化列表来初始化[答案] A2.如果一个类至少有一个纯虚函数,那么就称该类为()A. 抽象类B. 虚函数C. 派生类D. 以上都不对[答案] A3.下列描述中,()是抽象类的特征。
A. 可以说明纯虚函数B. 可以说明虚函数C. 可以定义友元函数D. 可以说明其对象[答案] A4.编译时的多态性可以通过使用( )获得。
A. 虚函数和指针B. 重载函数和析构函数C. 虚函数和对象D. 虚函数和引用[答案] C5.关于虚函数的描述中,正确的是()。
A. 虚函数是一个静态成员函数B. 虚函数是一个非成员函数C. 虚函数即可以在函数说明定义,也可以在函数实现时定义D. 派生类的虚函数与基类中对应的虚函数具有相同的参数个数和类型[答案] D6.下述静态成员的特性中,()是错误的。
A. 静态成员函数不能利用this指针B. 静态数据成员要在类体外进行初始化C. 引用静态数据成员时,要在静态数据成员名前加<类名>和作用域运算符D. 静态数据成员不是所有对象所共有的[答案] D7.下列运算符中,()运算符在C++中不能重载。
A. ?:B. []C. newD. &&[答案] A8.要实现动态联编,可以通过()调用虚函数。
A. 对象指针B. 成员名限定C. 对象名D. 派生类名[答案] A9.以下()成员函数表示纯虚函数。
A. virtual int vf(int);B. void vf(int)=0;C. virtual void vf()=0;D. virtual void vf(int) { };[答案] C10.关于纯虚函数和抽象类的描述中,错误的是()。
多态性与虚函数习题
多态性与虚函数习题一、选择题1.在C++中,用于实现运行时多态性的是()。
A)内联函数B)重载函数C)模板函数D)虚函数2.如果一个类至少有一个纯虚函数,那么就称该类为()。
(a)抽象类 (b)派生类 (c)虚基类 (d)以上都不对3.为了区分一元运算符的前缀和后缀运算,在后缀运算符进行重载时,额外添加一个参数,其类型是()。
(a)void (b)char (c)int (d)float4.下列关于抽象类的说明中不正确的是()。
(a)含有纯虚函数的类称为抽象类(b)抽象类不能被实例化,但可声明抽象类的指针变量(c)抽象类的派生类可以实例化(d)纯虚函数可以被继承5.运行下列程序的输出结果为()。
#include<iostream.h>class base{public:void fun1(){cout<<"base"<<endl;}virtual void fun2(){cout<<"base"<<endl;}};class derived:public base{public:void fun1(){cout<<"derived"<<endl;}void fun2(){cout<<"derived"<<endl;}};void f(base &b){b.fun1();b.fun2();}int main(){derived obj;f(obj);return 0;}(a)base (b)base (c)derived (d)derivedBase derived base derived6.下面描述中,正确的是()。
A.virtual可以用来声明虚函数B.含有纯虚函数的类是不可以用来创建对象的,因为它是虚基类C.即使基类的构造函数没有参数,派生类也必须建立构造函数D.静态数据成员可以通过成员初始化列表来初始化7. 关于虚函数的描述中,正确的是()。
实验十一_虚函数答案
实验十一_虚函数答案实验十一虚函数一、实验目的1)掌握虚函数的定义和使用2)掌握抽象类的定义和使用3)掌握纯虚函数的定义4)掌握虚析构函数、纯虚函数和抽象类的作用二、实验原理1.利用虚函数的作用:当编译器编译虚函数时,编译系统将用动态连接的方式进行编译。
即在编译时不确定该虚函数的版本,而是利用一种机制在运动过程中根据其所指向的实例决定使用哪一个函数版本。
2.利用虚析构函数的原则:当将基类指针或引用new运算符指向派生类对象时,为了在释放派生类对象时能调用派生类的析构函数,必须将基类的析构函数定义为虚函数。
3.抽象类的作用:为它的所有派生类提供一个公共接口,纯虚函数是定义抽象类的一种间接手段。
三、实验设备实验室里调备的计算机、window xp,visual c++6.0四、实验内容4.1分析下面各题程序,按各题的要求进行实验1)分析下面的程序,指出程序运行的结果:#includeclass CBase{public:virtual void f1() //将成员函数f1()声明为虚函数{cout<<"调用函数CBase::f1()!"<<endl;}< p="">virtual void f2() //将成员函数f2()声明为虚函数{cout<<"调用函数CBase::f2()!"<<endl;}< p="">void f3() //一般成员函数{cout<<"调用函数CBase::f3()!"<<endl;}< p=""> };class CDerived:public CBase //公有继承CBase {void f1(){cout<<"调用函数CDerived::f1()!"<<endl;}< p=""> void f2(){cout<<"调用函数CDerived::f2()!"<<endl;}< p=""> void f3(){cout<<"调用函数CDerived::f3()!"<<endl;}< p=""> };void main(){CBase obj1,*p; //定义CBase的对象obj1和指针对象p CDerived obj2; //定义CDerived的对象obj1p=&obj1 //将obj1的地址给pp->f1(); //通过p调用基类版本的f1()函数p->f2(); //通过p调用基类版本的f2()函数p->f3(); //通过p调用基类版本的f3()函数p=&obj2 //将派生类对象obj2的地址赋给pp->f1(); //动态连接,调用派生类版本p->f2(); //动态连接,调用派生类版本p->f3(); // 调用基类版本}运行的结果:调用函数CBase::f1()!调用函数CBase::f2()!调用函数CBase::f3()!调用函数CDerived::f1()!调用函数CDerived::f2()!调用函数CBase::f3()!Press any key to continue2)分析下面的程序,指出程序运行的结果:#includeclass CBase{public:CBase() //CBase类的构造函数{cout<<"调用构造函数CBase()!"<<endl;< p="">fun();} //构造函数中调用虚函数fun() virtual void fun() //定义虚函数{cout<<"调用构造函数CBase::fun()!"<<endl;}< p="">};class CDerived:public CBase{public:CDerived() //CDerived类的构造函数{cout<<"调用构造函数CDerived()!"<<endl;< p="">fun();} //构造函数中调用虚函数fun() void fun(){cout<<"调用构造函数CDerived::fun()!"<<endl;}< p="">};void main(){CDerived d; //创建对象d.fun();}运行结果:调用构造函数CBase()!调用构造函数CBase::fun()!调用构造函数CDerived()!调用构造函数CDerived::fun()!调用构造函数CDerived::fun()!Press any key to continue3)分析下面的程序,指出程序的错误#include#includeclass CBase{protected:char *ch;public:CBase(char *x){ch=new char[20];strcpy(ch,x);}virtual void fun()=0;virtual void fun1() //虚函数{cout<<x<<endl;}< p="">{cout<<ch<<endl;}< p="">~CBase(){delete[]ch; cout<<"~CBase()"<<endl;< p="">}};class CDerived:public CBase{protected:char *ch;public:CDerived (char *x,char*y):CBase(y){ch=new char[20];strcpy(ch,x);}void fun1()// {cout<<x<<endl;}< p="">{cout<<ch<<endl;}< p="">Virtual ~CDerived(){delete[]ch; cout<<"~CDerived()"<<endl;}< p=""> void main(){CBase obj1("Hello"),*p;p=&obj1p->fun1();p->fun();p=new CDerived("China","Hello"); p->fun1(); p->fun();delete p;}运行结果:HelloChina~CBase()~CBase()Press any key to continue修正后的源代码:#include#include#includeusing namespace std;class CBase{protected:char *ch;public:CBase(const char *x){ch = new char[20];strcpy(ch, x);}virtual void fun() {};virtual void fun1(){cout << ch << endl;};~CBase(){delete []ch;cout << "~CBase()" << endl;}};class CDerived: public CBaseprotected:char *ch;public:CDerived(const char *x, const char *y): CBase(y) {ch = new char[20];strcpy(ch, x);}void fun1(){cout << ch << endl;}~CDerived(){delete []ch;cout << "~CDerived()<<endl;";< p="">}};int main()CBase obj1("Hello"), *p;p = &obj1p->fun1();p->fun();p = new CDerived("China", "Hello");p->fun1();p->fun();delete p;return 0;}4.2编写并调试程序1)编写一个程序计算三角,正方形和圆形的面积。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3、(选做题) 某学校对教师每月工资的计算规定如下:固定工作+课时补 贴。教授的固定工作为5000元,每个课时补贴50元;副教授 的固定工资为3000元,每个课时补贴30元;讲师的固定工资 为2000元,每个课时补贴20元。定义教师抽象类,派生不同 职称的教师类,编写程序求若干个教师的月工资。
#include<iostream.h> class Rational { public : Rational (long n , long d=1) ; // 构造函数,把长整型转换成Rational类型 friend Rational operator+ ( const Rational & ,const Rational & ) ; friend ostream &operator<<(ostream &os, Rational &s); operator double() ; // 类型转换函数 private : long Numerator , Denominator ; }; Rational :: Rational(long n, long d) { Numerator = n ; Denominator = d ; } Rational :: operator dou Numerator ) / double( Denominator ); } Rational operator+ ( const Rational & r1, const Rational & r2 ) { long n , d ; n = r1.Numerator * r2.Denominator + r1.Denominator * r2.Numerator ; d = r1.Denominator * r2.Denominator ; return Rational( n, d ) ; }
实验内容——作业 作业 实验内容 1、编写一个程序,定义抽象基类Shape,由它派生出5个 派生类:Circle(圆形)、Square(正方形)、Rectangle(矩形 )、Trapezoid(梯形)、Triangle(三角形)。用虚函数分别计 算几种图形面积。要求用基类指针数组,使它每一个元 素指向一个派生类对象。 2 2、使用虚函数编写程序,求球体和圆柱体的体积和表面 积。由于球体和圆柱体都可以看做由圆继承而来,所以 可以定义圆类circle作为基类。在circle类中定义一个数 据成员radius和两个虚函数area()和volume()。由circle类 派生sphere类和column类。在派生类中对虚函数area()和 volume()重新定义,分别求球体和圆柱体的体积及表面 积。
ostream &operator<<(ostream &os, Rational &s) { os << s.Numerator << "/" << s.Denominator ; return os; } void main ( ) { Rational a( 2, 4 ), b = (1, 2), c( 0 ) ; c = a + b; // 使用友员重载 “+” 和 缺省重载 “=”