c++中virtual关键字的作用与Java中多态的一点对比

发布时间:2019-11-19 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了c++中virtual关键字的作用与Java中多态的一点对比脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

动机

最近一直在使用C++写win32程序,用了一些库,里面提供的类和demo各种是virtual这个关键字,一直不是很明白到底是啥用,于是查看了一些文档,写小程序来实验它的作用。

结论

virtual这个关键字的发挥作用是在子类去继承父类的时候。比如:

class PErson { public:     void foo1()     {         // do ...     }          virtual void foo2()      {         // do ...     } };

像上面的代码,如果类Person就一直被实例化使用,但是没有类去继承它的话,那么这个virtual实际上并没有什么卵用。foo2()方法和foo1()是一样的。

当它被继承的时候,有两种情况,覆写(override)这个foo2()方法,或者不覆写它。比如这样:

class Student : public Person { public:     void foo2() { // do something.. } };  class Teacher : public Person { public:     // no override };

然后我们使用的时候,如果是子类的实例,调用foo2()方法,理所当然是执行子类中所定义的foo2()方法体。但是当将这个子类的实例强制转型成父类的实例(指针),再去执行foo2()方法的时候,对应的两种情况:子类实现了父类中virtual方法的,调用子类的方法;子类中没有override的,仍然是调用父类中的实现(这不是废话么……)

列个表格大概是这样:

// 大前提是父类中有个`virtual`方法`foo2()`         是否override foo2()    调用子类实例的foo2()    强转成父类后调用foo2() 子类1          是                执行子类1的foo2()        执行子类1的foo2() 子类2          否                执行父类的foo2()         执行父类的foo2()  // 另一种情况 // 大前提是父类中有个方法`foo2()`,但是没有virtual关键字修饰         是否override foo2()    调用子类实例的foo2()    强转成父类后调用foo2() 子类1          是                执行子类1的foo2()        执行父类的foo2() 子类2          否                执行父类的foo2()         执行父类的foo2()

与Java的对比

我的感觉好像Java自带这个多态的特性,不需要用什么关键字修饰,某个实例转换成父类后调用方法,默认就会调用子类的实现(如果有的话)。写了个小demo实验了一下,果然如此。

public class Main {      public static void main(String[] args) {         Person p = new Person();         p.foo(); // output: Person foo                  Student s = new Student();         s.foo(); // output: Student foo                  Person ps = s;         ps.foo(); // output: Student foo      }          static class Person {                  public void foo() {             System.out.PRintln("Person foo");         }     }          static class Student extends Person {                  public void foo() {             System.out.println("Student foo");         }     }  }

在《Effective Java 2e》中,作者也说了,尽可能的在申明,传参,返回值的时候使用父类和接口,而不要使用实现类。

大概是这样:

ArrayList<String> strList = new ArrayList<String>();    //这样是耿直的写法 List<String> strList = new ArrayList<String>();    //这样更好,因为你可以换后面这个new  // 返回值和参数也是一样,一般能使用接口就尽量使用接口,而不要写死成实现类,这样带来更大的灵活性 public List<String> buildStrList(List<String> raw, AnyInterface interf) {     // do xxxx }

总结

  • virtual关键字修饰的方法在子类继承实现后,就可以达到多态的目的(使用父类的指针依然可以调用到子类的实现)。

  • Java中不需要这个关键字来达到多态,覆写方法自带这个功能。

参考

脚本宝典总结

以上是脚本宝典为你收集整理的c++中virtual关键字的作用与Java中多态的一点对比全部内容,希望文章能够帮你解决c++中virtual关键字的作用与Java中多态的一点对比所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。