C++与JAVA多态相同与不同
C++与Java中继承与多态是十分重要的特性,但在学习中发现并没有一篇将这两者做比较与总结,所以写下自己观点,本文中有自己的原创,也有引用网上经典的分析与例子,引用部分会说明并贴出链接。不足之处希望大家指正。
首先说一下Java与C++继承的不相同特性,也是最容易让人混淆的三个概念:重载,重写,重定义
重载overload:重载是同名函数具有不同的形参列表(参数类型或数量),只有在同一个类内的函数才能叫做重载。
重写Overriding:重写是C++中的概念,子类与父类有同名函数,仅仅只需要函数名称相同,形参表可以不同,则子类会覆盖父类的函数。虽然很多人在Java中也提到了重写的概念,但实际上是重定义(很快会给出解释),因为在Java中子类会继承父类同名但参数不同的函数,作为重载,而在C++中父类的同名函数是不会继承的。下面分别给出C++和Java的例子。
C++
1 class A 2 { 3 public: 4 void show(string s) 5 { 6 cout << s; 7 } 8 }; 9 class B:public A 10 { 11 public: 12 void show(int i) 13 { 14 cout << i; 15 } 16 17 }; 18 int main() 19 { 20 int i = 0; 21 string s = "1"; 22 B b; 23 b.show(i); 24 b.show(s); 25 26 }
以上代码编译后出现error C2664: “void B::show(int)”: 无法将参数 1 从“std::string”转换为“int”
可以看出B并没有继承A的参数为string的show函数,与此类似,但是在Java中就不一样了
Java
1 public class A { 2 public void show(String s) 3 { 4 System.out.println(s); 5 } 6 } 7 public class B extends A{ 8 public void show(int i) 9 { 10 System.out.println(i); 11 } 12 static public void main(String[]args){ 13 int i=0; 14 String s="1"; 15 B b=new B(); 16 b.show(i); 17 b.show(s); 18 19 } 20 21 }
以上代码会输出0,1;可以看出Java会继承父类的同名但形参不同的函数
重定义redefining:重定义是重写的加强版本,必须要求子类中函数名以及形参和父类完全相同,在C++中,子类不会继承父类同名函数,所以重定义自然在子类中唯一;在Java中由于函数与父类完全相同,所以重定义会覆盖父类的同名同参函数(这也是为什么上面我说很多人把重定义当成了重写),重定义是实现多态的关键技术。
下面来说多态,多态的实现机制C++与Java几乎是相同的,想要深入了解的可以参考一下C++多态实现机制。首先解释一下什么叫做多态。
多态是指父类引用子类对象,但是能够表现出子类的特性(调用子类的函数或方法)。
多态分为静态多态与动态多态,静态多态即使我不讲,你也已经会用了(其实就是重载);动态多态的实现需要两个关键技术:父类对子类的引用;子类重定义父类的虚函数。
在Java中,父类对子类的引用很自然,就像声明一个对象一样,而在C++中必须使用指针;另外Java中没有修饰符的函数都默认为虚函数,所以在子类中只需要重定义父类函数即可,而C++必须显示加上virtual修饰符,再重定义才可以。
下面分别是C++多态实现和Java多态实现。
C++
1 class A 2 { 3 public: 4 virtual void show() 5 { 6 cout <<"A"; 7 } 8 }; 9 class B:public A 10 { 11 public: 12 void show() 13 { 14 cout << "B"; 15 } 16 17 }; 18 int main() 19 { 20 A*p = new B(); 21 p->show(); 22 }
运行之后输出B,可以看出A的指针却调用了B类中的show函数。
Java
1 public class A { 2 public void show() 3 { 4 System.out.println("A"); 5 } 6 } 7 public class B extends A{ 8 public void show() 9 { 10 System.out.println("B"); 11 } 12 static public void main(String[]args){ 13 A p=new B(); 14 p.show(); 15 16 } 17 18 }
运行结果同样为B
以上为原创部分,割;接下来就要在理解清楚概念的基础上来点小练习了,下面的例子为转载,也很经典。
首先是Java的继承经典题目。引用自深入理解Java多态性
1 public class A { 2 public String show(D obj) { 3 return ("A and D"); 4 } 5 6 public String show(A obj) { 7 return ("A and A"); 8 } 9 10 } 11 12 public class B extends A{ 13 public String show(B obj){ 14 return ("B and B"); 15 } 16 17 public String show(A obj){ 18 return ("B and A"); 19 } 20 } 21 22 public class C extends B{ 23 24 } 25 26 public class D extends B{ 27 28 } 29 30 public class Test { 31 public static void main(String[] args) { 32 A a1 = new A(); 33 A a2 = new B(); 34 B b = new B(); 35 C c = new C(); 36 D d = new D(); 37 38 System.out.println(a1.show(b)); ① 39 System.out.println(a1.show(c)); ② 40 System.out.println(a1.show(d)); ③ 41 System.out.println(a2.show(b)); ④ 42 System.out.println(a2.show(c)); ⑤ 43 System.out.println(a2.show(d)); ⑥ 44 System.out.println(b.show(b)); ⑦ 45 System.out.println(b.show(c)); ⑧ 46 System.out.println(b.show(d)); ⑨ 47 } 48 } 49 50 51 答案: 52 ① A and A 53 ② A and A 54 ③ A and D 55 ④ B and A 56 ⑤ B and A 57 ⑥ A and D 58 ⑦ B and B 59 ⑧ B and B 60 ⑨ A and D
具体解释大家可以阅读原文,已经解释的十分清楚了,我想重点强调的是调用的优先问题 ,优先级由高到低依次为:this.show(Object)、super.show(O)、this.show((super)O)、super.show((super)O)。
接下来是C++的多态题目,引用自从一个面试题谈C++多态性
1 class A 2 { 3 public: 4 void foo() 5 { 6 printf("1\n"); 7 } 8 virtual void fun() 9 { 10 printf("2\n"); 11 } 12 }; 13 class B : public A 14 { 15 public: 16 void foo() 17 { 18 printf("3\n"); 19 } 20 void fun() 21 { 22 printf("4\n"); 23 } 24 }; 25 int main(void) 26 { 27 A a; 28 B b; 29 A *p = &a; 30 p->foo(); 31 p->fun(); 32 p = &b; 33 p->foo(); 34 p->fun(); 35 return 0; 36 } 37 38 答案:1214