附加静态联编动态联编多态实例
- 格式:doc
- 大小:66.00 KB
- 文档页数:10
Java基本概念:多态⼀、简介描述:多态性是⾯向对象编程中的⼀个重要特性,主要是⽤来实现动态联编的。
换句话说,就是程序的最终状态只有在执⾏过程中才被决定,⽽⾮在编译期间就决定了。
这对于⼤型系统来说能提⾼系统的灵活性和扩展性。
多态允许相同类域的不同对象对同⼀消息做出响应。
即同⼀消息可以根据发送对象的不同⽽采⽤多种不同的⾏为⽅式。
多态可以让我们不⽤关⼼某个对象到底是什么具体类型,就可以使⽤该对象的某些⽅法,从⽽实现更加灵活的编程,提⾼系统的可扩展性。
如果对象的编译时类型和运⾏时类型不⼀致,就会造成多态。
存在条件:1. 类之间有继承关系。
2. ⼦类重写⽗类⽅法。
3. ⽗类引⽤指向⼦类对象。
注意:多态是⽅法的多态,属性没有多态性。
⼀个对象的实际类型是确定的,但是可以指向这个对象的引⽤的类型,却是可以是这对象实际类型的任意⽗类型。
⼦类继承⽗类,调⽤⽅法,如果该⽅法在⼦类中没有重写,那么就是调⽤的是⼦类继承⽗类的⽅法,如果重写了,那么调⽤的就是重写之后的⽅法。
'protected'修饰的⽗类⽅法可以被⼦类见到,也可以被⼦类重写,但是它是⽆法被外部所引⽤的,所以没有多态性。
通过⼀个变量调⽤其引⽤的对象的⼀个⽅法,编译器是否能让其编译通过,主要是看该变量类型的类中有没有定义该⽅法,如果有则编译通过,如果没有则编译报错。
⽽不是看这个变量所引⽤的对象中有没有该⽅法。
Java中的⽅法调⽤,是运⾏时动态和对象绑定的,不到运⾏的时候,是不知道到底哪个⽅法被调⽤的。
编写程序时,如果想调⽤运⾏时类型的⽅法,只能进⾏类型转换,不然通不过编译器的检查。
但是如果两个没有关联的类进⾏强制转换,会报类型转换异常:ClassCastException。
⽰例:public class Test {public static void main(String[] args) {/* 编译看左,运⾏看右 */Student student = new Student();/* 变量person是可以指向Person类型或其⼦类型的对象,所以可以指向Student类型对象 */Person person = new Student();/* 变量student能调⽤的⽅法是Student类中有的⽅法(包括继承过来的) */student.say();//Student/* 变量person能调⽤的⽅法是Person类中有的⽅法 */person.say();//Student}}class Person {public void say() {System.out.println("Person");}}class Student extends Person {public void say() {System.out.println("Student");}}⼆、重写、重载、多态的关系1. 重载是编译时多态调⽤重载的⽅法,在编译期间就要确定调⽤的⽅法是谁,如果不能确定则编译报错。
多态性是C++最主要的特征,多态性的实现得益于C++中的动态联编技术。
文章通过对动态联编的关键技术虚拟函数表进行深入的剖析,解析的动态联编的过程极其技术要领。
关键字多态性动态联编 VTABLE 虚函数文章正文一从多态性谈动态联编的必要性在进入主题之前先介绍一下联编的概念。
联编就是将模块或者函数合并在一起生成可执行代码的处理过程,同时对每个模块或者函数调用分配内存地址,并且对外部访问也分配正确的内存地址。
按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编和动态联编。
在编译阶段就将函数实现和函数调用关联起来称之为静态联编,静态联编在编译阶段就必须了解所有的函数或模块执行所需要检测的信息,它对函数的选择是基于指向对象的指针(或者引用)的类型。
反之在程序执行的时候才进行这种关联称之为动态联编,动态联编对成员函数的选择不是基于指针或者引用,而是基于对象类型,不同的对象类型将做出不同的编译结果。
C语言中,所有的联编都是静态联编。
C++中一般情况下联编也是静态联编,但是一旦涉及到多态性和虚函数就必须使用动态联编。
多态性是面向对象的核心,它的最主要的思想就是可以采用多种形式的能力,通过一个用户名字或者用户接口完成不同的实现。
通常多态性被简单的描述为"一个接口,多个实现。
在C++里面具体的表现为通过基类指针访问派生类的函数和方法。
下面我们看一个静态联编的例子,这种静态联编导致了我们不希望的结果。
//1.cpp1. #include <iostream.h>2. class shape{3. public:4. void draw(){cout<<"I am shape"<<endl;}5. void fun(){draw();}6. };7. class circle:public shape{8. public:9. void draw(){cout<<"I am circle"<<endl;}10. };11. main(){12. class circle oneshape;13. oneshape.fun();14. }程序的输出结果我们希望是"I am circle",但事实上却输出了"I am shape"的结果,造成这个结果的原因是静态联编。
程序代码:(1)静态联编的例子——试图显示派生类信息#include<iostream>#include<cmath>using namespace std;class CShape //基类{public:double Perimeter(){return 0;}//计算周长double Area(){return 0;} //计算面积};class CRectangle:public CShape //矩形{private:double w,h;public:CRectangle(double x,double y){w=x;h=y;}double Perimeter(){return (w+h)*2;}//同名覆盖double Area(){return w*h;} //同名覆盖};class CCircle:public CShape { //圆private:double r;public:CCircle(double x){r=x;}double Perimeter(){return 3.1415926*r*2;}//同名覆盖double Area(){return 3.1415926*r*r;} //同名覆盖};class CTriangle:public CShape { //三角形private:double a,b,c;public:CTriangle(double x,double y,double z){a=x,b=y,c=z;} double Perimeter(){return a+b+c;}//同名覆盖double Area()//计算圆的面积{double p = ( a + b + c) / 2.0;return sqrt(p * ( p - a)*(p- b)*(p - c));}};//全局函数show()显示各种形状的周长和面积void show(CShape & s) {cout << "周长:" << s.Perimeter()<< endl;cout << "面积:" << s.Area() << endl;}int main(){CCircle cl(5.0);cout<<"圆的信息:"<<endl;show(cl);cout<<"************************************"<<endl;CRectangle rect(100,50);cout<<"矩形的信息:"<<endl;show(rect);cout<<"************************************"<<endl;CTriangle tri(3,4,5);cout<<"三角形的信息:"<<endl;show(tri);return 0;}程序运行结果:圆的信息:周长:0面积:0***********************************矩形的信息:周长:0面积:0***********************************三角形的信息:周长:0面积:0(2)动态联编的例子——(使用基类指针)#include<iostream>#include<cmath>using namespace std;class CShape //基类{public:virtual double Perimeter(){return 0;}//虚函数,计算周长virtual double Area(){return 0;} //虚函数,计算面积};class CRectangle:public CShape //矩形{private:double w,h;public:CRectangle(double x,double y){w=x;h=y;}double Perimeter(){return (w+h)*2;}//同名覆盖double Area(){return w*h;} //同名覆盖};class CCircle:public CShape { //圆private:double r;public:CCircle(double x){r=x;}double Perimeter(){return 3.1415926*r*2;}//同名覆盖double Area(){return 3.1415926*r*r;} //同名覆盖};class CTriangle:public CShape { //三角形private:double a,b,c;public:CTriangle(double x,double y,double z){a=x,b=y,c=z;} double Perimeter(){return a+b+c;}//同名覆盖double Area()//计算圆的面积{double p = ( a + b + c) / 2.0;return sqrt(p * ( p - a)*(p- b)*(p - c));}};//全局函数show()显示各种形状的周长和面积void show(CShape * p) {cout << "周长:" << p->Perimeter()<< endl;cout << "面积:" << p->Area() << endl;}int main(){CCircle cl(5.0);cout<<"圆的信息:"<<endl;show(&cl);cout<<"************************************"<<endl;CRectangle rect(100,50);cout<<"矩形的信息:"<<endl;show(&rect);cout<<"************************************"<<endl;CTriangle tri(3,4,5);cout<<"三角形的信息:"<<endl;show(&tri);return 0;}程序运行结果:圆的信息:周长:31.4159面积:78.5398************************************矩形的信息:周长:300面积:5000************************************三角形的信息:周长:12面积:6(3)动态联编的例子——改进(使用基类引用)#include<iostream>#include<cmath>using namespace std;class CShape //基类{public:virtual double Perimeter(){return 0;}//虚函数,计算周长virtual double Area(){return 0;} //虚函数,计算面积};class CRectangle:public CShape //矩形{private:double w,h;public:CRectangle(double x,double y){w=x;h=y;}double Perimeter(){return (w+h)*2;}//同名覆盖double Area(){return w*h;} //同名覆盖};class CCircle:public CShape { //圆private:double r;public:CCircle(double x){r=x;}double Perimeter(){return 3.1415926*r*2;}//同名覆盖double Area(){return 3.1415926*r*r;} //同名覆盖};class CTriangle:public CShape { //三角形private:double a,b,c;public:CTriangle(double x,double y,double z){a=x,b=y,c=z;} double Perimeter(){return a+b+c;}//同名覆盖double Area()//计算圆的面积{double p = ( a + b + c) / 2.0;return sqrt(p * ( p - a)*(p- b)*(p - c));}};//全局函数show()显示各种形状的周长和面积void show(CShape & s) { //全局函数的形参为基类引用cout << "周长:" << s.Perimeter()<< endl;cout << "面积:" << s.Area() << endl;}int main(){CCircle cl(5.0);cout<<"圆的信息:"<<endl;show(cl);//函数的实参为派生类对象,下同cout<<"************************************"<<endl;CRectangle rect(100,50);cout<<"矩形的信息:"<<endl;show(rect);cout<<"************************************"<<endl;CTriangle tri(3,4,5);cout<<"三角形的信息:"<<endl;show(tri);return 0;}程序运行结果:圆的信息:周长:31.4159面积:78.5398************************************矩形的信息:周长:300面积:5000************************************三角形的信息:周长:12面积:6(4)游戏《魔法门之英雄无敌》——非多态的实现方法(部分代码) class CCreature {protected: int nPower ; //代表攻击力int nLifeValue ; //代表生命值};class CDragon:public CCreature {public:void Attack(CWolf * pWolf) {//...表现攻击动作的代码pWolf->Hurted( nPower);pWolf->FightBack( this);}void Attack( CGhost * pGhost) {//...表现攻击动作的代码pGhost->Hurted( nPower);pGohst->FightBack( this);}void Hurted ( int nPower) {// ....表现受伤动作的代码nLifeValue -= nPower;}void FightBack( CWolf * pWolf) {// ....表现反击动作的代码pWolf ->Hurted( nPower / 2);}void FightBack( CGhost * pGhost) {// ....表现反击动作的代码pGhost->Hurted( nPower / 2 );}}(5)游戏《魔法门之英雄无敌》——多态的实现方法(部分代码) //基类CCreature:class CCreature {protected :int m_nLifeValue, m_nPower;public:virtual void Attack( CCreature * pCreature) {}virtual void Hurted( int nPower) { }virtual void FightBack( CCreature * pCreature) { } };//派生类 CDragon:class CDragon : public CCreature {public:virtual void Attack( CCreature * pCreature);virtual void Hurted( int nPower);virtual void FightBack( CCreature * pCreature);};void CDragon::Attack(CCreature * p){//…表现攻击动作的代码p->Hurted(m_nPower); //多态p->FightBack(this); //多态}void CDragon::Hurted( int nPower){//…表现受伤动作的代码m_nLifeValue -= nPower;}void CDragon::FightBack(CCreature * p){//…表现反击动作的代码p->Hurted(m_nPower/2); //多态}(6)游戏《魔法门之英雄无敌》——多态的实现方法(部分代码)#include<iostream>#include<stdlib.h>#include<math.h>using namespace std;class CShape{public:virtual double Area() = 0; //纯虚函数virtual void PrintInfo() = 0;};class CRectangle:public CShape{public:int w,h;virtual double Area();virtual void PrintInfo();};class CCircle:public CShape {public:int r;virtual double Area();virtual void PrintInfo();};class CTriangle:public CShape {public:int a,b,c;virtual double Area();virtual void PrintInfo();};double CRectangle::Area() {return w * h;}void CRectangle::PrintInfo() {cout << "Rectangle:" << Area() << endl; }double CCircle::Area() {return 3.14 * r * r ;}void CCircle::PrintInfo() {cout << "Circle:" << Area() << endl; }double CTriangle::Area() {double p = ( a + b + c) / 2.0;return sqrt(p * ( p - a)*(p- b)*(p - c));}void CTriangle::PrintInfo() {cout << "Triangle:" << Area() << endl;}CShape * pShapes[100];int MyCompare(const void * s1, const void * s2);int main(){int i; int n;CRectangle * pr; CCircle * pc; CTriangle * pt;cin >> n;for( i = 0;i < n;i ++ ) {char c;cin >> c;switch(c){case'R':pr = new CRectangle();cin >> pr->w >> pr->h;pShapes[i] = pr;break;case'C':pc = new CCircle();cin >> pc->r;pShapes[i] = pc;break;case'T':pt = new CTriangle();cin >> pt->a >> pt->b >> pt->c;pShapes[i] = pt;break;}}qsort(pShapes,n,sizeof( CShape*),MyCompare);for( i = 0;i <n;i ++)pShapes[i]->PrintInfo();return 0;}int MyCompare(const void * s1, const void * s2) {double a1,a2;CShape * * p1 ; // s1,s2 是void * ,不可写“* s1”来取得s1指向的内容CShape * * p2;p1 = ( CShape * * ) s1; //s1,s2指向pShapes数组中的元素,数组元素的类型是CShape *p2 = ( CShape * * ) s2; // 故p1,p2都是指向指针的指针,类型为CShape **a1 = (*p1)->Area(); // * p1 的类型是Cshape * ,是基类指针,故此句为多态a2 = (*p2)->Area();if( a1 < a2 )return -1;else if ( a2 < a1 )return 1;elsereturn 0;}程序运行结果:3R 3 5C 9T 3 4 5Triangle:6Rectangle:15Circle:254.34。