当前位置:文档之家› 实验八 多态性

实验八 多态性

实验八多态性1.填空(1)关键字operator 引入了重载运算符函数定义。

(2)不能重载的C++运算符是类属关系运算符"."、成员指针运算符".*"、作用域分辨符"::" 、sizeof运算符和三目运算符"?:" 。

(3)通过重载运算符不能修改运算符的操作对象个数、优先级、和结合性。

2、选择题,先选择,然后解释选择的理由:(1) 运算符重载时不需要保持的性质是:(A )A)操作数类型B)操作数个数C)优先级D)结合性解释:通过重载运算符不能修改运算符的操作对象个数、优先级、和结合性。

但其他的可以改变。

(2) 有如下类定义和变量定义:#include<iostream.h>class X{int a;void setX (int x){a=x;}public:void showX(){cout<<"a="<<a<<endl;}};class Y: private X{/*类定义省略*/};class Z: public X{/*类定义省略*/};Y objY;Z objZ;下列语句中正确的是:( D )A) objY.setX(3);B) objY.showX();C) objZ.setX(4);D) objZ.showX();解释:对于A,C,无论何种继承方式,派生类均不可直接访问基类的私有成员。

对于B,由于Y继承X时是私有继承,派生类Y不可直接访问X中的成员。

(3) 有如下类定义:#include<iostream.h>class A{ int xx;public:A():xx(0){cout<<'A';}A(int n):xx(n){cout<<'B';}};class B:public A{ int yy;public:B():yy(0){cout<<yy;}B(int n):A(n+1),yy(n){cout<<yy;}B(int m,int n):A(m),yy(n){cout<<yy;}};下列选项中,输出结果为A0的语句是:( D ) A)B y1(0,0);B)B y2(1);C)B y3(0);D)B y4;解释:输出结果分别为B0B1B0A0(4)有如下程序:class A{ public:A() { f();}~A() { ...... }virtual void f();void g(){f()};};class B: public A{ public:~B() { ...... }void f();void g();};B b; A *p; p = &b;没有调用到A::f的语句是:( A)A) p->f();B) p->A::f();C) p = new A;D) p = new B;解释:分别调用,A)调用B::f;B)调用A::f();C)调用A::f();D)调用B::B(),A::A(),A::f(5)己知表达式a++中的“++”是作为友元函数重载的运算符,则与a++等效的运算符函数调用形式为:( C)A)a .orerator++(1);B)operator++(a);C)operator++(a, 0);D)a.operator++(a, 0 );解释:由于是作为友元函数重载,根据由友元函数重载的规则,可排除ABD。

(6)有如下程序:#include <iostream.h>class Base{public:virtual void fn(int x){ cout<<"Base::fn()"<<endl; }};class Sub : public Base{public:virtual void fn(double x){ cout<<"Sub::fn()"; }};void test(Base& b){b.fn(2);}int main(){Base a; test(a);Sub b; test(b);}执行的结果是:( A )A) Base::fn() Base::fn()B) Base::fn() Sub::fn()C) Sub::fn() Base::fn()D) Sub::fn() Sub::fn()解释:由于派生类的fn函数参数类型为double型,与基类类型不同,导致派生类的虚函数不能覆盖基类的虚函数,从而调用时均调用的是基类的fn函数。

3.#include <iostream>using namespace std;class Point{public:Point (int val) { x = val; }Point Point::operator++() //前置++运算符重载{ x++; return *this; }Point Point::operator ++(int) //后置++运算符重载{ Point old = *this;++(*this);return old;}int GetX() { return x; }private:int x;};int main(){ Point a(10);cout << (++a).GetX();cout << a++.GetX(); }4.#include<iostream.h>class Second;class First{private:int t;public:First(int x) { t=x; }void print(Second &b);};class Second{private: int s;public:Second(int y) { s=y; }friend void First::print(Second & w);};void First::print(Second & w){cout<<"First: "<<t<<" Second: "<<w.s<<endl;}int main(){ First m(6);Second n(8);m.print(n) ;return 0;}5.#include<iostream>using namespace std;class CShape{ public:virtual float area()=0;};float total(CShape *s[ ],int n) //n为图形的个数{ float sum=0.0; //各图形面积和for(int i=0;i<n;i++)sum+=s[i]->area();return sum;}class CTriangle:public CShape{public:CTriangle(float w=0,float h=0);float area(){return W*H*0.5;};private:float W,H;};class CRectangle:public CShape{public:CRectangle(float w=0,float h=0);float area(){return W*H;};private:int W,H;};CTriangle::CTriangle(float w,float h){W=w;H=h;}CRectangle::CRectangle(float w,float h){W=w;H=h;}int main(){float fArea;CTriangle s1(1,2);CRectangle s2(3,4);CShape *s[]={&s1,&s2};fArea=total(s,2);cout<<fArea<<endl;}6、友元运算符函数和成员运算符函数有什么不同?哪些运算符只能用友元?哪些运算符只能用成员函数?哪些两者均可?解:不同点:运算符函数如果是类的成员函数,则它具有一个隐含的this指针,this所指对象就成为第一个操作数。

即用成员运算符函数表示一个双目运算符,该成员运算符函数有一个参数,表示第二个操作数;用成员运算符函数表示一个单目运算符,该成员运算符函数有没有参数。

运算符运算符函数如果是类的友元函数,则它没有this指针。

即用友元运算符函数表示一个双目运算符,该函数有两个参数;用友元运算符函数表示一个单目运算符,该函数有一个参数。

友元运算符函数总是比成员运算符函数多一个函数参数。

只能用友元函数:第一个操作数不是类的操作对象。

只能用成员函数:这些运算符是:=(赋值)、[](下标)、()(函数调用)、->(通过指针访问成员),以及所有的类型转换运算符。

两者均可:在多数情况下,将运算符重载为类的成员函数和类的友元函数都是可以的。

在多数情况下,将运算符重载为类的成员函数和类的友元函数都是可以的。

但成员函数运算符与友元函数运算符也具有各自的一些特点:(1) 一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。

(2) 以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。

(3) 类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。

(4) 若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。

(5) 若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。

(6) 当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。

如果左边的操作数必须是一个不同类的对象,或者是一个内部类型的对象,该运算符函数必须作为一个友元函数来实现。

(7) 当需要重载运算符具有可交换性时,选择重载为友元函数。

7、判断对错,说明理由:(1)重载函数和运算符都是是用静态联编实现的。

因为:C++在编译时常采用“名字压延“的方法来区分重载函数。

名字压延是在编译器“看”到函数后改变函数名。

亦即C++把重载函数的本名和参数结合起来创造函数的新名字,在程序中每一处说明原型、定义和调用这些函数的地方,C++均用压延名字来替代。

例如:有以下两个函数原型:int myAns(float x,int j);int myAns(int i,char c);并用以下语句调用它们:exam1=myAns(15,3,15);exam2=myAns(45,’a’);则在编译完成之前,C++也许会将函数名改变成如下形式:int myAnsFLTINT(float x,int j);int myAnsINTCHAR(int I,char c);同时C++也会在函数调用的地方改变名字,如:exam1=myansFLTINT(15,3,15);exam2=myAnsINTCHAR(45,’a’);解:对。

相关主题