C++模板和Java泛型之间的不同

许多人都认为模板template和泛型generic这两个概念是等价的,因为两者都允许我们按照List<String>的样式编写代码。

不过,各种语言是怎么实现该功能,以及为什么这么做,却千差万别。

Java的泛型的实现根植于“类型消除”这一概念。当源代码被转换成Java虚拟机字节码时,这种技术会消除参数化类型。

例如,假设有一下java 代码:


    
    
  1. Vector<String> vector = new Vector<String>();
  2. vector.add( new String( “hello”));
  3. String str = vector.get( 0);

编译时,上面的代码会被改写为:


    
    
  1. Vector vector = new Vector();
  2. vector.add( new String( "hello"));
  3. String str = (String)vector.get( 0);

有了Java泛型,我们可以做的事情也并没有真正改变多少;它只是让代码变得漂亮些。鉴于此,Java泛型有时也被成为”语法糖“。

这点跟C++的模板截然不同。

在C++中,模板本质上就是一套宏指令集,只是换了个名头,编译器会针对每种类型创建一份模板代码的副本。

有个证据可以证明这一点:MyClass<Foo>不会与MyClass<Bar>共享静态变量。然而,两个MyClass<Foo>实例则会共享静态变量。

扫描二维码关注公众号,回复: 2697128 查看本文章


    
    
  1. /*
  2. * MyClass.cpp
  3. *
  4. * Created on: 2015?7?24?
  5. * Author: nanzhou
  6. */
  7. template< class T> class MyClass {
  8. public:
  9. static int val;
  10. MyClass( int v) {val = v;}
  11. };
  12. template< typename T> int MyClass<T>::bar;
  13. template class MyClass<Foo>;
  14. template class MyClass<Bar>;
  15. MyClass<Foo>* foo1 = new MyClass<Foo>( 10);
  16. MyClass<Foo>* foo2 = new MyClass<Foo>( 15);
  17. MyClass<Bar>* bar1 = new MyClass<Bar>( 20);
  18. MyClass<Bar>* bar2 = new MyClass<Bar>( 35);
  19. int f1 = foo1->val; //15
  20. int f2 = foo2->val; //15
  21. int b1 = bar1->val; //35
  22. int b2 = bar2->val; //35

但在Java中,MyClass类的静态变量会由所有MyClass实例共享,无论类型参数相与否。


由于架构设计上的差异,Java泛型和C++模板还有如下很多不同点;

1. C++模板可以使用int等基本数据类型。Java则不行,必须转而使用Integer

2. Java中,可以将模板的类型参数限定为某种特定类型。例如,你可能会使用泛型实现CardDeck,并规定参数必须扩展自CardGame。

3. C++中,类型参数可以实例化,Java不可以实例化

4. Java中,类型参数(即MyClass<Foo>中的Foo)不能用于静态方法和变量,因为他们会被MyClass<Foo>和MyClass<Bar>共享。但在C++中,这些类是不同的,类型参数可以用于静态方法和静态变量。

5. 在Java中,不管类型参数是什么,MyClass的所有实例都是同一类型。类型参数会在运行时被抹去。而C++中,参数类型不同,实例类型也不同


Java的泛型和C++模板,虽然在很多方面看起来都一样,实则大不相同。

            </div>

许多人都认为模板template和泛型generic这两个概念是等价的,因为两者都允许我们按照List<String>的样式编写代码。

不过,各种语言是怎么实现该功能,以及为什么这么做,却千差万别。

Java的泛型的实现根植于“类型消除”这一概念。当源代码被转换成Java虚拟机字节码时,这种技术会消除参数化类型。

例如,假设有一下java 代码:


  
  
  1. Vector<String> vector = new Vector<String>();
  2. vector.add( new String( “hello”));
  3. String str = vector.get( 0);

编译时,上面的代码会被改写为:


  
  
  1. Vector vector = new Vector();
  2. vector.add( new String( "hello"));
  3. String str = (String)vector.get( 0);

有了Java泛型,我们可以做的事情也并没有真正改变多少;它只是让代码变得漂亮些。鉴于此,Java泛型有时也被成为”语法糖“。

这点跟C++的模板截然不同。

在C++中,模板本质上就是一套宏指令集,只是换了个名头,编译器会针对每种类型创建一份模板代码的副本。

有个证据可以证明这一点:MyClass<Foo>不会与MyClass<Bar>共享静态变量。然而,两个MyClass<Foo>实例则会共享静态变量。


  
  
  1. /*
  2. * MyClass.cpp
  3. *
  4. * Created on: 2015?7?24?
  5. * Author: nanzhou
  6. */
  7. template< class T> class MyClass {
  8. public:
  9. static int val;
  10. MyClass( int v) {val = v;}
  11. };
  12. template< typename T> int MyClass<T>::bar;
  13. template class MyClass<Foo>;
  14. template class MyClass<Bar>;
  15. MyClass<Foo>* foo1 = new MyClass<Foo>( 10);
  16. MyClass<Foo>* foo2 = new MyClass<Foo>( 15);
  17. MyClass<Bar>* bar1 = new MyClass<Bar>( 20);
  18. MyClass<Bar>* bar2 = new MyClass<Bar>( 35);
  19. int f1 = foo1->val; //15
  20. int f2 = foo2->val; //15
  21. int b1 = bar1->val; //35
  22. int b2 = bar2->val; //35

但在Java中,MyClass类的静态变量会由所有MyClass实例共享,无论类型参数相与否。


由于架构设计上的差异,Java泛型和C++模板还有如下很多不同点;

1. C++模板可以使用int等基本数据类型。Java则不行,必须转而使用Integer

2. Java中,可以将模板的类型参数限定为某种特定类型。例如,你可能会使用泛型实现CardDeck,并规定参数必须扩展自CardGame。

3. C++中,类型参数可以实例化,Java不可以实例化

4. Java中,类型参数(即MyClass<Foo>中的Foo)不能用于静态方法和变量,因为他们会被MyClass<Foo>和MyClass<Bar>共享。但在C++中,这些类是不同的,类型参数可以用于静态方法和静态变量。

5. 在Java中,不管类型参数是什么,MyClass的所有实例都是同一类型。类型参数会在运行时被抹去。而C++中,参数类型不同,实例类型也不同


Java的泛型和C++模板,虽然在很多方面看起来都一样,实则大不相同。

            </div>

猜你喜欢

转载自blog.csdn.net/coding_is_fun/article/details/81564512