所以看两段小程序:
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.youkuaiyun.com/clam_clam/article/details/6919645 。
至于动态绑定机制可以参考博客:http://blog.youkuaiyun.com/clam_clam/article/details/6831975。
对于虚函数有几点需要注意:
1.虚函数只需在基类声明即可,在类外不必在家virtual 。
2.同样基类某一函数声明为虚函数( 包括纯虚函数)后子类同名函数自动成为虚函数(派生类虚函数可以加virtual 也可以不加,一般为了程序清晰加上virtual 关键字)。
3.构造函数不能声明为虚函数。因为在执行构造函数时类对象还未完成建立过程,谈不上函数与类对象的关联。
4.析构函数最好声明为虚函数。这样无论指针指向类族中哪一个对象,当对象撤销时,系统会采用动态关联调用相应的析构函数,对该对象进行清理。
5.虚函数是可以调用的注意与纯虚函数区分开来。纯虚函数只是为派生类保留一个名字,纯虚函数不能被调用,同样包含纯虚函数的抽象类无法建立对象。
6.抽象类作为一个类族共同基类,为一个类族提供公共接口。抽象类虽然不能实例化但可以定义抽象类指针,通过该指针指向派生类调用相应虚函数实现多态性操作。