所以看两段小程序:
1. Java 程序:
package com; class Student{ int num; String name; double score; Student(int num,String name,double score){ this.name=name; this.num=num; this.score=score; } void display(){ System.out.println("Student.display: "+this); } @Override public String toString() { return "Student [name=" + name + ", num=" + num + ", score=" + score + "]"; } } class Graduate extends Student{ double pay; Graduate(int num,String name,double score,double pay){ super(num,name,score); this.pay=pay; } void display(){ System.out.println("Graduate.display: "+this); } @Override public String toString() { return "Graduate [pay=" + pay + ", name=" + name + ", num=" + num + ", score=" + score + "]"; } } public class TA {//总结C++ 和java 在多态实现上区别。 public static void main(String []args){ Student stu=new Student(1001,"LI",98.5); stu.display(); stu=new Graduate(1002,"Wang",87.9,79.9); stu.display(); } }
运行结果为:
Student.display: Student [name=LI, num=1001, score=98.5] Graduate.display: Graduate [pay=79.9, name=Wang, num=1002, score=87.9]//执行Student类的display()代码。
2. C++ 程序:
#include <iostream> #include <string> using namespace std; class Student { public: Student(int num,string name,float score){ this->num=num; this->name=name; this->score=score; } void dispaly(){ cout<<"num:"<<num<<"\nname:"<<name<<"\nscore:"<<score<<endl; } protected: int num; string name; float score; }; class Graduate:public Student{ private: float pay; public: Graduate(int num,string name,float score,float pay):Student(num,name,score),pay(pay){} void dispaly(){ cout<<"num:"<<num<<"\nname:"<<name<<"\nscore:"<<score<<"\npay:"<<pay<<endl; } }; int main(int argc, char* argv[]) { Student stu1(1001,"Li",98.5); Graduate grad1(1002,"Wang",87.9,79.9); Student *pt=&stu1; pt->dispaly(); cout<<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>"<<endl; pt=&grad1; pt->dispaly();//从输出结果来看,pt->display还是调用Student 类里的display 函数(没有输出pay)。 return 0; }
运行结果为:
num:1001 nameLi score98.5 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> num:1002 nameWang score87.9 Press any key to continue
从这两段代码比较java 和c++多态有几点不同:
1.java 里用基类引用指向子类,自动会调用子类方法。
2.C++ 里用基类指针指向子类,函数还是调用基类函数代码快,尽管数据是子类对象数据。pt=&grad1; pt->display();没有输出pay。
3.C++ 如果要实现多态的话要声明为虚函数。
如果我们在display 前加一个virtual 关键字
virtual void dispaly(){ cout<<"num:"<<num<<"\nname:"<<name<<"\nscore:"<<score<<endl; }
运行结果就会截然不同。
运行结果为:
num:1001 name:Li score:98.5 >>>>>>>>>>>>>>>>>>>>>>>>>>>>> num:1002 name:Wang score:87.9 pay:79.9 Press any key to continue
4.没有声明为虚函数由于是Student pt 类指针,所以指针指向Student 类函数代码区。 而声明为虚函数后在对象块有一个虚函数表记录着,子类dispaly 函数。这样就执行了子类的display 函数。可以参考博客:http://blog.csdn.net/clam_clam/article/details/6919645 。
至于动态绑定机制可以参考博客:http://blog.csdn.net/clam_clam/article/details/6831975。
对于虚函数有几点需要注意:
1.虚函数只需在基类声明即可,在类外不必在家virtual 。
2.同样基类某一函数声明为虚函数(包括纯虚函数)后子类同名函数自动成为虚函数(派生类虚函数可以加virtual 也可以不加,一般为了程序清晰加上virtual 关键字)。
3.构造函数不能声明为虚函数。因为在执行构造函数时类对象还未完成建立过程,谈不上函数与类对象的关联。
4.析构函数最好声明为虚函数。这样无论指针指向类族中哪一个对象,当对象撤销时,系统会采用动态关联调用相应的析构函数,对该对象进行清理。
5.虚函数是可以调用的注意与纯虚函数区分开来。纯虚函数只是为派生类保留一个名字,纯虚函数不能被调用,同样包含纯虚函数的抽象类无法建立对象。
6.抽象类作为一个类族共同基类,为一个类族提供公共接口。抽象类虽然不能实例化但可以定义抽象类指针,通过该指针指向派生类调用相应虚函数实现多态性操作。