面向对象与UML建模作业 下载本文

virtulfloatarea() //声明为虚函数 {return0.0;} };

constfloatPi=3.141593;

classCircle:publicPoint //定义派生类Circle { private: floatradius; public: Circle(floatr) {radius=r;}

virtulfloatarea() {returnPi3radius3radius;} };

voidmain(){

Point3pp; //指向基类的指针pp Circlec(5.4321); pp=&c;

cout<area()<

} //调用虚函数,执行派生类中定义的函数area()

从上面例子可看出,利用虚函数可在基类和派生类中使用相同的函数名定义函数的不同实现,从而实现“一个接口,多种方式”.一般说来,外部函数不能声明为虚函数,成员函数(除构造函数)都可以声明为虚函数.然而,在处理虚函数时,要动态确定应该选用哪一版本函数,故它比标准函数需要更多的存储空间.因此,虚函数仅用于处理派生类中一系列同名、同参数和同返回值的函数.

类型参数化多态类型。参数化多态是指当1个函数(或类)对若干个类型参数操作时,这些类型具有某些公共的语义特性,可以用该函数(或类)来描述这些公共语义特性.C++中的模板是实现类型参数化多态的工具,分为类模板和函数模板。

类模板一个类模板可以表示一组类.下面是一个通用栈类,它可以存放整数、字符或类对象.

#includetemplateclassstack //stack类模板 { T3v; T3p; intsz;

public: stack(ints) {v=p=newT[sz=s];} ~stack() {delete[]v;} voidpush(Ta) {3p++=a;}

Tpop(){return322p;}

intsize()const{returnp2v;} }

voidmain()

{stacksch(20); //stack类模板用char实例化后创建对象

stacksi(20); //stack类模板用int实例化后创建对象sch.push(’a’);si.push(10);∶}

其中,stack类模板中带有一个类型参数T,表示栈中存放对象的类型,它不是实际类型,因此不能用类模板直接生成实例对象.通过对类模板的实例化(即给类模板的参数指定具体类型的过程),类模板实例化后的结果是类而不是实例对象,因此可用类模板实例化后的结果类产生实例对象.在main()函数中,从stack类模板实例化了两个模板类:stack和stack,然后又由这两个模板类分别实例化各自对象:sch和si.

函数模板与类模板相似,可以定义操纵一组类型的函数.下面定义了一个求两对象间的最大值的函数模版。templateTmax(Ta,Tb){returna>b?a:b;}该函数模板可以求int,char,float指针或任何重载了>运算符的类对象间的最大值.函数模板也要实例化,实例化后就生成了具体的函数代码(即特定于参数的类型),与类模板不同的是,它的实例化不需要用户显式进行,而是在函数调用时由编译器来处理.例如:inta,b;charc,d;intm1=max(a,b);//调用max(inta,intb);intm2=max(c,d);//调用max(charc,chard);事实上,函数模板表示了一组名字相同的函数,这些函数之间以及这些函数与其它同名函数之间是重载函数的关系.在使用函数模板时,应保证函数的参数与模板函数的参数正好相配,因为编译器不会给模板函数的参数提供任何形式的转换.总之,模板描述了一组类或一组函数,避免了为各种不同的数据类型进行重复的编码工作

重载多态重载是多态性中最简单的形式.它是指用同一名字表示不同的函数或运算符,从而使C++具有更大的灵活性和扩展性.它分为运算符重载和重载函数两种.

重载函数重载函数是指同一作用域内名字相同、但参数不同的函数. 例如:#include intfunc(intx,inty) {returnx

floatfunc(floatx,floaty){returnx

{intn1=8,n2=10;

cout<<“themaxis:”<

cout<<“themaxis:”<

cout<<“themaxis:”<

运行结果为: themaxis:10 themaxis:4.3 themaxis:4.9上述3个函数,函数名相同,函数参数不同,因为编译器是根据参数来识别重载函数,所以必须保证重载函数的参数有所不同,即两重载函数必须具有以下两种差别之一才能分辨。 ①函数的参数个数不同;②一个或多个参数的类型不同。

运算符重载C++的基本类型(int,char,float等以及它们的派生类型)既能描述数据的存储格式,又能描述施加在数据上的操作,这种操作用运算符来指定。在基本类型中运算符都按系统预定义好的方式来工作。为了使用户定义的类型与基本类型一样,C++也允许用户定义类型使用运算符来表示操作。实质上,运算符可以看成是一种函数,即运算符函数,只是对于基本类型,函数都是编译器给定

的,不能加以改动。但对于类对象,用户却可以重新定义运算符函数,以便设置运算符在类对象中新的含义。因此,定义运算符在某类对象操作的做法即所谓的运算符重载。运算符函数可以是类的成员函数,也可以是非成员函数,如果是非成员函数,一般将它声明为该类的友员。

例:classcomplex //复数类

{//...public: Complexoperator+(constComplex&com) {Complextemp(rpart+com.rpart,ipart+com.ipart); returntemp;}//...};

运算符函数operator+被定义为公有的,程序中的其它函数可以调用它,在定义了该函数之后,就可以像基本类型一样对复数对象用+表达式实施运算。当程序中有语句Complexa(10,7),b(3,5),c;c=a+b;时,C++编译器把表达式a+b解释为函数调用a.operator+(b),在调用时,operator+成员函数首先创建一个临时Complex类对象temp,然后把出现在加法表达式中的两个复数之和暂存其内,最后将这个临时对象返回。

强制多态强制也称类型转换,是指将一种类型的值转换成另一种类型的值而进行的语义操作,从而防止类型错误。类型转换可以是隐式的,在编译阶段完成;也可以是显式的,在运行阶段完成。 基本数据类型之间的类型转换C++定义了基本数据类型之间的转换原则,即低高当两个操作对象类型不一致时,在算术操作之前级别低的自动转换成级别高的类型。用户定义类型的转换着重介绍类类型与其它数据类型之间的转换。 (2)java实现多态的技术

Java基本上是通过重载、接口、继承 这三种方式实现多态。

①JAVA里没有多继承,一个类之能有一个父类。 而继承的表现就是多态。一个父类可以有多个子类,而在子类里可以重写父类的方法(例如方法

print()),这样每个子类里重写的代码不一样,自然表现形式就不一样。这样用父类的变量去引用不同的子类,在调用这个相同的方法print()的时候得到的结果和表现形式就不一样了,这就是多态,相同的消息(也就是调用相同的方法)会有不同的结果。举例说明: //父类

public class Father{ //父类有一个打孩子方法 public void hitChild(){} }

//子类1

public class Son1 extends Father{ //重写父类打孩子方法 public void hitChild(){

System.out.println(\为什么打我?我做错什么了!\}

//子类2

public class Son2 extends Father{

//重写父类打孩子方法 public void hitChild(){ System.out.println(\我知道错了,别打了!\}

//子类3

public class Son3 extends Father{

//重写父类打孩子方法 public void hitChild(){ System.out.println(\我跑,你打不着!\}

//测试类

public class Test{

public static void main(String args〔〕){

Father father;

father = new Son1(); father.hitChild(); father = new Son2(); father.hitChild(); father = new Son3(); father.hitChild(); } }

都调用了相同的方法,出现了不同的结果。这就是多态的表现。

②JAVA中没有多继承,而用接口实现了多继承。一个类或是可以同时实现多个接口。(就相当于C++里一个类同时继承了多个类。)例如: public class Son implements Father1,Father2,Father3{ }

接口有利于代码功能的扩展(增加新的功能)。而继承则有利于代码功能的修改(把旧的功能改成新的功能)。这里旧功能的修改和新功能的增加前提是不修改旧的功能,旧的功能仍然可以使用,旧类的代码也不做修改。 接着上面的继承举例:上面例子中的子类我们统称为一代子类 ⅰ.用继承修改旧的功能。

现在如果一代Son1的功能打孩子,也就是方法hitChild()里边的功能实现有问题,我们要把具体实现修改掉,那么我们可以重新写一个新的二代子类Son11继承自一代子类Son1,并重写其hitChild()方法。 //二代子类

public class Son11 extends Son1{ //重写父类打孩子方法

public void hitChild(){ System.out.println(\我是二代子类对此方法的新实现\}