C++模板概述

来源:互联网 发布:思科arp绑定mac地址 编辑:程序博客网 时间:2024/06/01 10:20

简介

只有使用C++语言的少数用户才努力尝试去理解模板的基本原理。然而那些希望去探索更多高级用法的人往往发现自己需要努力去理解模板是如何被语言所支持的,因为缺乏明确的说明。一个很大的问题在于一些工具只实现了C++标准的一个子集。本文将指出它们共同的缺陷并深入剖析如何使用C++模板快速产生可重用和高效的代码。

模板功能应用的典型是通过一系列模板类形成的完整类库,特别是STL和ATL。标准C++库(STL)提供了很多可重用和灵活的类及算法,而ATL则是使用C++进行COM编程的事实标准。要掌握这些及其它的模板库,理解模板是如何工作的这一基础是非常重要的。

函数模板

int main()
{
    0 cout<<add(2,3)<<endl;
    1 cout<<add(2.1,3)<<endl;
    2 cout<<add(2,3.2)<<endl;
    3 cout<<add(2.2,3.3)<<endl;
    4 cout<<add("hello eone ","world")<<endl;
    return 0;
}

     也可以通过宏定义#define add(a,b) ((a)+(b))来实现,但是指针(字符串)不能直接相加.对于2,3,4需要进行模板特化.

通过重载函数,我们能够完成多种不同数据类型的相同操作。要实现两个double数值的加法和两个整数类型的加法,我们可以使用一个重载函数:

  int add(const int x, const int y)

  {

    return x + y;

  }

  double add(const double x, const double y)

  {

    return x + y;

  }

这时,编译器将根据它们的参数正确地解决这一问题。

//    调用int add(const int, const int);

const int z1 = add(3, 2);

      //    调用double add(const double, const double);

      const double z2 = add(3.0, 2.0);

如果我们需要处理其它类型,我们就不得不提供其他函数重载。对每个不同的数据类型实现一个函数重载,它们都遵循相同的模式,每当我们需要调用针对某一数据类型的函数时,原则上编译器为我们生成相应的代码。而一个模板函数则以如下方式实现:

  template<class T>

  const T add(const T &t1, const T &t2)

  {

    return t1 + t2;

  }

从概念上来说,编译器通过模板关键字(后面跟随着模板由一或多个模板参数构成的参数列表)来识别模板。当为某一具体类型调用add时,编译器将根据模板定义并用给定的类型替换出现在模板中的参数。在这个例子中,模板参数列表由一个独立的类型模板参数T构成。使用一个模板函数替代函数重载,编译器可以自动为所需的新类型生成代码

我们可以对任何拥有+操作符定义的类型使用add模板。假设一个自定义的String类提供了字符串连接并知道如何将自身写入到std::ostream。因为String与该模板函数兼容,因此我们可以调用它来实现字符串相加:

  //    示例字符串

  const string strBook("book");

  const string strWorm("worm");

//    显示 "bookworm".

  cout << add(strBook, strWorm) << endl;

Seeing that we intended to add two String values, the compiler will generate the appropriate add function on our behalf, which would look something like:

  const String add(const String &t1, const String &t2)

  {

    return t1 + t2;

  }

显式实例化

调用模板函数时,编译器将先把正确的类型实例化模板。虽然标准允许显式模板实例化,然而并非所有厂商都能够正确地实例它。例如,Visual C++ 6.0 会潜在地调用错误的函数::

  template<class T>

  int getSize(void) {

    return sizeof(T);

  }

  //    输出4,应该为8

  cout << "double: " << getSize<double>() << endl;

//    输出4,正确

  cout << "int: " << getSize<int>() << endl;

跨平台代码设计者不希望依赖于显式模板函数实例化,除非有更好的编译器能够对它提供有效的支持

0 0