c++学习java学习--java中有没有虚函数

https://blog.csdn.net/wuqiuping695/article/details/49069779


前几天面试京东的时候,被问到c++与java函数的区别。其中有一条是,java中有没有虚函数?本文将从虚函数的定义java字节码层面上告诉你答案。


一、虚函数的定义

定义:在某基类中声明为 virtual 并在一个或多个派生类中被重新定 义的成员函数,用法格式为:virtual 函数返回类型 函数名(参数表) {函数体};实现多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。----------(百度百科)


举个c++中虚函数的例子:

[cpp]  view plain  copy
  1. #include<iostream>  
  2. using namespace std;  
  3. class A  
  4. {  
  5.     public:  
  6.         void FUN()  
  7.         {  
  8.             cout<<"FUN in A is called"<<endl;  
  9.         }  
  10. };  
  11.    
  12. class B : public A  
  13. {  
  14.     public:  
  15.         void FUN()  
  16.         {  
  17.             cout<<"FUN in B is called"<<endl;  
  18.         }  
  19. };  
  20.    
  21. int main()  
  22. {  
  23.     A a;  
  24.     B b;  
  25.     a.FUN();  
  26.     b.FUN();  
  27.     return 0;  
  28. }  
运行可以得到结果:

FUN in A is called

FUN in B is called


代码小改一下:

[cpp]  view plain  copy
  1. #include<iostream>  
  2. using namespace std;  
  3. class A  
  4. {  
  5.     public:  
  6.         void virtual FUN()  
  7.         {  
  8.             cout<<"FUN in A is called"<<endl;  
  9.         }  
  10. };  
  11.    
  12. class B : public A  
  13. {  
  14.     public:  
  15.         void FUN()  
  16.         {  
  17.             cout<<"FUN in B is called"<<endl;  
  18.         }  
  19. };  
  20.    
  21. int main()  
  22. {  
  23.     A a;  
  24.     B b;  
  25.     A *p;  
  26.     p = &a;  
  27.     p->FUN();  
  28.     p = &b;  
  29.     b.FUN();  
  30.     return 0;  
  31. }  

同样可以得到运行结果:

FUN in A is called

FUN in B is called


读者可以试试将第6行的关键字virtual去掉试运行下,会发现,运行结果如下:

FUN in A is called

FUN in A is called


通过这个例子,可以看到虚函数的作用------实现多态。指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。


再来看看java语言,

[java]  view plain  copy
  1. package test;  
  2.   
  3. /** 
  4.  * Created by ping on 2015/10/12. 
  5.  */  
  6. class A{  
  7.     public void FUN(){  
  8.         System.out.println("FUN in A is called");  
  9.     }  
  10. }  
  11. class B extends A{  
  12.     public void FUN(){  
  13.         System.out.println("FUN in B is called");  
  14.     }  
  15. }  
  16. public class VirtualTest {  
  17.   
  18.     public static void main(String args[])  {  
  19.         A a = new A();  
  20.         B b = new B();  
  21.         A p;  
  22.   
  23.         p = a;  
  24.         p.FUN();  
  25.         p = b;  
  26.         p.FUN();  
  27.     }  
  28. }  

在上面的代码中,我们同样定义了一个基类指针(在java中应该叫引用)去指向不同的对象,可以发现同样可以实现多态。 也就是说,java的普通成员函数(没有被static、native等关键字修饰)就是虚函数,原因很简单,它本身就实现虚函数实现的功能------多态。


下面,我们从更底层的方面来讲述java中虚函数。


二、java字节码

还是之前的代码,我们用javac编译之后,编译器会生成相应的class字节码文件。通过java自带字节码查看器查看

javap -verbose VirtualTest


上面字节码中,有许多指令,如aload_2、invokespecial、invokevirtual(注:aload指令是用来将数据加载到栈,invokespecial用来调用类的构造函数,invokevirtual用来调用普通函数)。


可以发现,对于A.FUN的调用,java虚拟机所采用的调用方式就是invokevirtual。这些字节码的调用指令,是由《java虚拟机规范》规定的,在制定规范之初,大牛们就直接用invokevirtual来命名调用普通函数的指令。从字节码指令的命名上也可以看出,java中的普通成员函数就是虚函数。


从网上有看到这样一种说法,大家可以作为一个参考。

C++                    Java

虚函数     --------   普通函数
纯虚函数   --------   抽象函数
抽象类     --------   抽象类

虚基类     --------   接口 


结论:java类中普通成员函数就是虚函数。


猜你喜欢

转载自blog.csdn.net/u010029439/article/details/80640782