• C++模板学习


     一、定义函数模板

    template<class T>

    函数定义

    举个例子比较两个数大小:

     1 template<class T>
     2 
     3 int Compare(T a,T b)
     4 
     5 {
     6 
     7   if(a>b)return 1;
     8 
     9   if(a<b)return -1;
    10 
    11   return 0;
    12 
    13 }
    14 
    15 int main()
    16 {
    17  int a=10;
    18  int b=11;
    19  char c='w';
    20  char d='w';
    21  double e=3.1415;
    22  double f=2.123;
    23  cout<<Compare(a,b)<<endl;
    24  cout<<Compare(c,d)<<endl;
    25  cout<<Compare(e,f)<<endl;
    26  return 0;
    27 }
    View Code


    二、定义类模板

      template<参数列表>

      类定义

      1、在定义类模板之前要先说明一个问题,因为这几天把C++中头文件的声明和定义学习了一下。刚好碰到类模板的学习,因此就此小试牛刀。但是这一试让我郁闷呢了好长时间,因为我还是和往常一样把类的声明放在一个*.h的头文件中,具体实现放在*.cpp文件中。但是让我很很很是郁闷的是,构造函数老是编译不能通过老是出现下面这个错误:

     error LNK2001: unresolved external symbol "public: __thiscall LinkList<char>::LinkList<char>(void)" (??0?$LinkList@D@@QAE@XZ)
    Debug/TemplateLinkList.exe : fatal error LNK1120: 1 unresolved externals

    我勒个擦,我最怕这种东西,查阅了好多资料一直没发现是哪有问题,最后终于在今天在网上看到了这篇博文才知道自己C++真是太水了:(http://www.cnblogs.com/tonyyang132/archive/2009/11/12/1601868.htmlhttp://bbs.csdn.net/topics/70471835

    按照C++中代码的惯例,类声明在h文件中,类定义在cpp文件中,相应的成员函数声明也在h文件中,定义在cpp文件中。但是如果这样的架构用在模板函数中,在调用模板函数的地方链接器便会报错,error LNK2001: unresolved external symbol。将定义写在与声明相同的文件中问题解决,解释如下:

     

    “大部分编译器在编译模板时都使用包含模式。也就是一般使用的把模板放到头文件中再包含。
    当你不使用这个模版函数或模版类,编译器并不实例化它。当你使用时,编译器需要实例化它。因为编译器是一次只能处理一个编译单元,也就是一次处理一个cpp文件,所以实例化时需要看到该模板的完整定义,所以都放在头文件中。
    这不同于普通的函数,在使用普通的函数时,编译时只需看到该函数的声明即可编译,而在链接时由链接器来确定该函数的实体。”

      2、在写类模板之前还要注意一点,在类模板作用域内,可以用他的非限定名字引用该类。比如:

      

    #ifndef NODE_H_H
    #define NODE_H_H
    template<class T>class LinkList;
    template<class T>
    class Node
    {
        friend LinkList<T>;
    private:
        T Data;
        Node *Next;//完整为Node<T> *Next;
    };
    #endif

    此处的Node<T> *Next可以写为Node *Next,但是为了保证不出错无论在不在类模板的作用域内都用它的限定名引用该类。还有注意一点假设有一个成员函数返回的是指向该模板类的指针,返回类型也必须为该模板的限定名引用该类。

     1 template <class T>
     2 Node<T> *LinkList<T>::Create(int len)//注意这里的返回值为类模板类型Node<T>
     3 {
     4     Node<T> *p;
     5     Node<T> *temp;
     6     T s;
     7     while(len--)
     8     {
     9         cout<<"输入数据:"<<endl;
    10         cin>>s;
    11         temp=new Node<T>;
    12         temp->Data=s;
    13         temp->Next=NULL;
    14         if (!head)
    15         {
    16             head=temp;
    17             p=head;
    18         }
    19         else
    20         {
    21             p->Next=temp;
    22             p=temp;
    23         }
    24     }
    25     return head;
    26 }

      3、因为这里是用类写而且class Node{};成员为私有,因此在class LinkList{};使用Node类的数据成员要在class Node{};声明为friend。

      4、贴出完整代码和运行结果。 

      1 //Node.h
      2 #ifndef NODE_H_H
      3 #define NODE_H_H
      4 template<class T>class LinkList;
      5 template<class T>
      6 class Node
      7 {
      8     friend LinkList<T>;
      9 private:
     10     T Data;
     11     Node *Next;
     12 };
     13 #endif
     14 /*-------------------------------------------*/
     15 //LinkList.h
     16 #include "Node.h"
     17 #ifndef LINKLIST_H_H
     18 #define LINKLIST_H_H
     19 template<class T>
     20 class LinkList
     21 {
     22 private:
     23     Node<T> *head;
     24 public:
     25     LinkList();
     26     ~LinkList();
     27     void Insert(T data);
     28     void printLinkList();
     29     Node<T> *Create(int len);
     30 };
     31 #endif
     32 
     33 template<class T>
     34 LinkList<T>::LinkList()
     35 {
     36     head=NULL;
     37 }
     38 
     39 template<class T>
     40 LinkList<T>::~LinkList()
     41 {
     42     Node<T> *p;
     43     while(head)
     44     {
     45         p=head->Next;
     46         delete head;
     47         head=p;
     48         cout<<"析构!"<<endl;
     49     }    
     50 }
     51 template <class T>
     52 Node<T> *LinkList<T>::Create(int len)
     53 {
     54     Node<T> *p;
     55     Node<T> *temp;
     56     T s;
     57     while(len--)
     58     {
     59         cout<<"输入数据:"<<endl;
     60         cin>>s;
     61         temp=new Node<T>;
     62         temp->Data=s;
     63         temp->Next=NULL;
     64         if (!head)
     65         {
     66             head=temp;
     67             p=head;
     68         }
     69         else
     70         {
     71             p->Next=temp;
     72             p=temp;
     73         }
     74     }
     75     return head;
     76 }
     77 template<class T>
     78 void LinkList<T>::Insert(T data)
     79 {
     80     Node<T> *p=head;
     81     Node<T> *s=new Node<T>;
     82     s->Data=data;
     83     s->Next=NULL;
     84     if (head==NULL)
     85     {
     86         head=s;
     87         
     88     }
     89     else
     90     {
     91         while(p->Next)
     92         {
     93             p=p->Next;
     94         }
     95         p->Next=s;
     96     }
     97 }
     98 
     99 template<class T>
    100 void LinkList<T>::printLinkList()
    101 {
    102     Node<T> *p=head;
    103     while(p)
    104     {
    105         cout<<p->Data<<endl;
    106         p=p->Next;
    107 
    108     }
    109 }
    110 /*--------------------------------------------------------------------*/
    111 //TemplateLinkList.cpp
    112 #include <iostream>
    113 #include<string>
    114 #include "Node.h"
    115 #include "LinkList.h"
    116 using namespace std;
    117 
    118 int main()
    119 {
    120     LinkList<char> L;
    121     L.Insert('a');
    122     L.Insert('b');
    123     L.Insert('c');
    124     L.printLinkList();
    125 
    126     LinkList<string> s;
    127     s.Insert("abcd");
    128     s.Insert("efgh");
    129     s.Insert("ijkl");
    130     s.printLinkList();
    131 
    132     LinkList<int> t;
    133     t.Insert(1);
    134     t.Insert(2);
    135     t.Insert(3);
    136     t.printLinkList();
    137 
    138     LinkList<double> d;
    139     Node<double> *b;
    140     b=d.Create(4);
    141     d.printLinkList();
    142 
    143     //Node<int> n;
    144     return 0;
    145 }
    View Code

     

      

  • 相关阅读:
    java1.5新特性
    [转载]传智播客_SQL入门
    集合类的应用
    多线程的应用
    包的使用
    异常的应用finally与总结
    自定义异常以及runtime类
    异常的处理
    SpringMVC_05 利用spring框架来处理异常
    SpringMVC_04 拦截器 【拦截器的编程步骤】【session复习?】
  • 原文地址:https://www.cnblogs.com/maxiaofang/p/3353148.html
Copyright © 2020-2023  润新知