精华内容
下载资源
问答
  • 类模板

    千次阅读 2018-08-03 11:31:18
    什么是类模板?  模板的目的就是为了淡化数据类型的要求,作出通用数据类型的模板。类中的成员变量和成员函数都牵涉到了数据类型。  在成员函数、成员变量以及基类中包含有类型参数的类称为类模板。  和函数...

    什么是类模板?

           模板的目的就是为了淡化数据类型的要求,作出通用数据类型的模板。类中的成员变量和成员函数都牵涉到了数据类型。

           在成员函数、成员变量以及基类中包含有类型参数的类称为类模板。

           和函数模板一样,类模板只是一个模板,并不是真正的类。

    形式:template<class T1, class T2, ... ,class Tn>
              class className
              { ... };

     

    类模板与函数模板的异同

    类模板和函数模板都需要二次编译

          我们看到函数模板的原理是二次编译。同样的类模板也需要二次编译。

    类模板 -- 实例化为 -> -- 实例化为 -> 对象

           类模板先在编译期的时候实例化为类,再在运行的时候实例化为真正的对象。其实类中的这个二次编译也叫二次实例化。

    类不能隐式推断

    我们在上一篇中讲到了函数模板的隐式推断,但是类模板却不能隐式推断。

     

    class_template.cpp

    #include <iostream>
    using namespace std;
    
    template <typename T>           //声明
    class Complex;
    
    template <typename T>           
    ostream &operator << (ostream &out, const Complex<T> &c);
    
    
    
    //模板类
    template <typename T>             //作用域很小
    class Complex
    {
    	friend ostream &operator << <T> (ostream &out, const Complex<T> &c);   
    	//将该函数声明成模板函数 
    	/*
    	friend ostream &operator << (ostream &out,const Complex<T> &c)    //全局函数可以在类的内部实现
    	{
    		out << c.m_a << "+" << c.m_b << "i" ;
    		return out;
    	}
    	*/
    private:
    	T m_a;
    	T m_b;
    public:
    	Complex(T a, T b);
    	void print();
    };
    
    template <typename T>
    Complex<T>::Complex(T a, T b)          //函数放在外面需要在Complex后面加上<T>
    {
    	m_a = a;
    	m_b = b;
    }
    
    template <typename T>
    void Complex<T>::print()
    {
    	cout << m_a << "+" << m_b << "i" << endl;
    }
    
    //该函数放在外面就要系很多声明
    template <typename T> 
    ostream &operator << (ostream &out, const Complex<T> &c)  //Complex是模板类
    {
    	out << c.m_a << "+" << c.m_b << "i" ;
    	return out;
    }
    
    
    int main()
    {
    	Complex<int> c(1, 2);    //类模板是一定要显式调用的
    	//c.print();
    	
    	cout << c << endl;
    	
    	return 0;
    }

     

    #include <iostream>
    using namespace std;
    
    
    template <typename T>
    class A                      //模板类
    {
    private:
    	T m_a;
    public:
    	A(T a);
    	//void print();
    };
    
    template <typename T>
    A<T>::A(T a)
    {
    	m_a = a;
    }
    
    
    class B : public A<int>     //模板类派生普通类
    {
    private:
    	int m_b;
    public:
    	B(int b);
    	
    };
    
    B::B(int b) : A<int>(1)     //一定要显式调用
    {
    	m_b = b;
    }
    
    
    template <typename T ,typename T2>
    class C : public A<T2>      //模板类派生模板类
    {
    private:
    	T m_c;
    public:
    	C(T c, T2 a);
    };
    
    template <typename T ,typename T2>
    C<T, T2>::C(T c, T2 a) : A<T2>(a)      //也要显式调用
    {
    	m_c = c;
    }
    
    
    int main()
    {
    	B b(1);
    	C<int, double> c(1,2.57);
    	
    	return 0;
    }
    

     

     

    展开全文
  • 类模板和模板类

    万次阅读 多人点赞 2019-07-04 21:10:42
    类模板和模板类 所谓类模板,实际上是建立一个通用类,其数据成员、成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表。使用类模板定义对象时,系统会实参的类型来取代类模板中虚拟类型从而实现了...

    类模板和模板类

    所谓类模板,实际上是建立一个通用类,其数据成员、成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表。使用类模板定义对象时,系统会实参的类型来取代类模板中虚拟类型从而实现了不同类的功能。

    定义一个类模板与定义函数模板的格式类似,必须以关键字template开始,后面是尖括号括起来的模板参数,然后是类名,其格式如下:

    template <typename 类型参数>
    class 类名{
           类成员声明 
    };
    
    或者
    
    template <class 类型参数>
    class 类名{
           类成员声明 
    };
    
    1. template:是一个声明模板的关键字,它表明声明一个模板

    2. 类型参数:通常用C++标识符表示,如T、Type等,实际上是一个虚拟的类型名,现在未指定它是哪一种具体的类型,但使用类模板时,必须将类型参数实例化。

    3. typename和class的作用相同,都是表示其后面的参数是一个虚拟的类名(即类型参数).

    在类声明中,欲采用通用数据类型的数据成员、成员函数的参数或返回类型前面需要加上类型参数。

    如建立一个用来实现求两个数最大值的类模板

    template<typename T>    //模板声明,其中T为类型参数
        class Compare{
          public:
           Compare(T i,T j)
           {
            x = i;
            y = j;
           }
           T max()
           {
            return (x>y)?x:y;
           } 
          private:
           T x,y; 
        };
    

    用类模板定义对象时,采用以下形式:

    类模板名<实际类型名>对象名[(实参表列)];
    

    因此,使用上面求最大值的类型模板的主函数可写成:

     int main()
         {
          Compare<int>com1(3,7);
          Compare<double>com2(12.34,56.78);
          Compare<char>com3('a','x');
          cout<<"其中的最大值是:"<<com1.max()<<endl;
          cout<<"其中的最大值是:"<<com2.max()<<endl;
          cout<<"其中的最大值是:"<<com3.max()<<endl;
          return  0;
         }    
    

    例6.6 类模板compare的使用举例

    #include<iostream.h>
    template<typename T>    //模板声明,其中T为类型参数
    class Compare{
      public:
        Compare(T i,T j)
        {
          x = i;
          y = j;
        }
        T max()
         {
          return (x>y)?x:y;
         } 
     private:
        T x,y; 
    };
    int main()
    {
    Compare<int>com1(3,7);                       //用类模板定义对象com1,此时T被int替代 
    Compare<double>com2(12.34,56.78);            //用类模板定义对象com2,此时T被double替代 
    Compare<char>com3('a','x');                  //用类模板定义对象com3,此时T被char替代 
    cout<<"其中的最大值是:"<<com1.max()<<endl;   
    cout<<"其中的最大值是:"<<com2.max()<<endl;
    cout<<"其中的最大值是:"<<com3.max()<<endl;
    return  0;
    }
    

    程序运行结果是:

    其中的最大值是:7
    其中的最大值是:56.78
    其中的最大值是:x        
    

    在以上例子中,成员函数(其中含有类型参数)是定义类体内的。但是,类模板中的成员函数,也可以在类模板外定义。此时,若成员函数中有参数类型存在,则C++有一些特殊的规定:

    (1)需要在成员函数定义之前进行模板声明;
    (2)在成员函数名前缀上"类名<类型参数>::";
    

    在类模板外定义成员函数的一般形式如下:

    temlate<typename 类型参数>
      函数类型 类名<类型参数>::成员函数名(形参表)
      {
        函数体; 
       }
       
       如上题中成员函数max在类模板外定义时,应该写成:
       template<typename T>
       T Compare<T>::max()
       {
        return (x>y)?x:y;
       } 
    

    //例6.7 在类模板外定义成员函数函数举例。

    #include<iostream.h>
    template<typename T>    //模板声明,其中T为类型参数
    class Compare{
      public:
        Compare(T i,T j)
        {
          x = i;
          y = j;
        }
        T max(); 
     private:
        T x,y; 
    };
    template<class T>
    T Compare<T>::max()
    {
     return (x>y)?x:y;
    }
    int main()
    {
    Compare<int>com1(3,7);                       //用类模板定义对象com1,此时T被int替代 
    Compare<double>com2(12.34,56.78);            //用类模板定义对象com2,此时T被double替代 
    Compare<char>com3('a','x');                  //用类模板定义对象com3,此时T被char替代 
    cout<<"其中的最大值是:"<<com1.max()<<endl;   
    cout<<"其中的最大值是:"<<com2.max()<<endl;
    cout<<"其中的最大值是:"<<com3.max()<<endl;
    return  0;
    } 
    

    /*
    程序运行结果是:

        其中的最大值是:7
        其中的最大值是:56.78
        其中的最大值是:x
    

    此例中,类模板Compare经实例化后生成了3个类型分别为int、double、char的模板类,这3个模板类
    经实例化后又生成了3个对象com1、com2、com3。类模板代表了一类类,模板类表示某一具体的类。关系如下:

                                             类模板
                                            Compare<T>
        实例化成模板类:Compare<int>       Compare<double>     Compare<char>
        实例化模板类对象:com1                 com2                com3
    

    例6.8 类模板Stack的使用举例。

    #include<iostream.h>
    const int size=10;
    template<class T>                     //模板声明,其中T为类型参数 
    class Stack{                          //类模板为Stack 
     public:
      void init()
      {
       tos=0;
      }
      void push(T ob);                    //声明成员函数push的原型,函数参数类型为T类型
      T pop();                            //声明成员函数pop的原型,其返回值类型为T类型
     private:
      T stack[size];                      //数组类型为T,即是自可取任意类型 
      int tos; 
    };
    template<class T>                     //模板声明 
    void Stack<T>::push(T ob)             //在类模板体外定义成员函数push 
    {
      if(tos==size)
       {
        cout<<"Stack is full"<<endl;
        return;
       }
      stack[tos]=ob;
      tos++; 
    }
    template<typename T>                  //模板声明 
    T Stack<T>::pop()                               //在类模板体外定义成员函数push
    {
      if(tos==0)
       {
        cout<<"Stack is empty"<<endl;
        return 0;
       }
      tos--; 
      return stack[tos];  
    }
    int main()
    {
     //定义字符堆栈 
     Stack<char> s1;                        //用类模板定义对象s,此时T被char取代
     s1.init();
     s1.push('a');
     s1.push('b');
     s1.push('c'); 
     for(int i=0;i<3;i++){cout<<"pop s1:"<<s1.pop()<<endl;}
     
     //定义整型堆栈 
     Stack<int> s2;                        //用类模板定义对象s,此时T被int取代
     s2.init();
     s2.push(1);
     s2.push(3);
     s2.push(5); 
     for(int i=0;i<3;i++){cout<<"pop s2:"<<s2.pop()<<endl;} 
     
     return 0; 
    }
    

    /*
    程序运行结果是:

    pop s1:c
    pop s1:b
    pop s1:a
    pop s2:5
    pop s2:3
    pop s2:1 
    

    说明:

    1. 在每一个类模板定义之前,都需要在前面加上模板声明,如

      template

      template
      并且,类模板在使用时,必须在模板类名字后面缀上<类型参数> ,如
      Stack

    2. 如同模板函数一样,模板类也可以有多个类型参数。

    例6.9 有两个类型参数的类模板举例

    #include<iostream.h>
    template<class QQ,class T>                    //声明模板,具有T1,T2两个类型参数 
    class Myclass{                                 //定义模板类Myclass 
      public:
       Myclass(QQ a,T b);
       void show();
      private:
       QQ x;
       T y;
    };
    template<typename QQ,typename T>
    Myclass<QQ,T>::Myclass(QQ a,T b)
    {
     x = a;
     y = b;
    }
    template<class QQ,class T>
    void Myclass<QQ,T>::show()
    {
     cout<<"x="<<x<<","<<"y="<<y<<endl;
    }
    int main()
    {
     Myclass <int,double>m1(12,0.15);               //用类模板定义对象m1,此时T1,T2分别被int、double取代 
     Myclass <int,char*>m2(12,"This a test.");      //用类模板定义对象m2,此时T1,T2分别被int,char*取代
    
     m1.show();
     m2.show();
     
     return 0; 
    }
    /*
    程序运行结果是:
    x=12,y=0.15
    x=12,y=This a test. 
    */
    

    程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!
    更多C++相关知识体系,请移步C++知识目录

    展开全文
  • C++类模板和模板类

    万次阅读 多人点赞 2018-11-29 14:32:35
    C++通过类模板来实现泛型支持。 1 基础的类模板 类模板,可以定义相同的操作,拥有不同数据类型的成员属性。 通常使用template来声明。告诉编译器,碰到T不要报错,表示一种泛型. 如下,声明一个普通的类模板: ...

    C++
    中有一个重要特性,那就是模板类型。类似于Objective-C中的泛型。C++通过类模板来实现泛型支持。

    1 基础的类模板

    类模板,可以定义相同的操作,拥有不同数据类型的成员属性。

    通常使用template来声明。告诉编译器,碰到T不要报错,表示一种泛型.

    如下,声明一个普通的类模板:

    template <typename T>
    class Complex{
        
    public:
        //构造函数
        Complex(T a, T b)
        {
            this->a = a;
            this->b = b;
        }
        
        //运算符重载
        Complex<T> operator+(Complex &c)
        {
            Complex<T> tmp(this->a+c.a, this->b+c.b);
            return tmp;
        }
            
    private:
        T a;
        T b;
    }
    
    int main()
    {
        //对象的定义,必须声明模板类型,因为要分配内容
        Complex<int> a(10,20);  
        Complex<int> b(20,30);
        Complex<int> c = a + b;
        
        return 0;
    }
    
    

    2 模板类的继承

    在模板类的继承中,需要注意以下几点:

    • 如果父类自定义了构造函数,记得子类要使用构造函数列表来初始化
    • 继承的时候,如果子类不是模板类,则必须指明当前的父类的类型,因为要分配内存空间
    • 继承的时候,如果子类是模板类,要么指定父类的类型,要么用子类的泛型来指定父类
    template <typename T>
    class Parent{
    public:
        Parent(T p)
        {
            this->p = p;
        }
        
    private:
        T p;
    };
    
    //如果子类不是模板类,需要指明父类的具体类型
    class ChildOne:public Parent<int>{
        
    public:
        ChildOne(int a,int b):Parent(b)
        {
            this->cone = a;
        }
        
    private:
        int cone;
    };
    
    
    //如果子类是模板类,可以用子类的泛型来表示父类
    template <typename T>
    class ChildTwo:public Parent<T>{
        
    public:
        ChildTwo(T a, T b):Parent<T>(b)
        {
            this->ctwo = a;
        }
        
    private:
        T ctwo;
    };
    
    

    3 内部声明定义普通模板函数和友元模板函数

    普通模板函数和友元模板函数,声明和定义都写在类的内部,也不会有什么报错。

    template <typename T>
    class Complex {
        
        //友元函数实现运算符重载
        friend ostream& operator<<(ostream &out, Complex &c)
        {
            out<<c.a << " + " << c.b << "i";
            return out;
        }
        
    public:
        Complex(T a, T b)
        {
            this->a = a;
            this->b = b;
        }
        
        //运算符重载+
        Complex operator+(Complex &c)
        {
            Complex temp(this->a + c.a, this->b + c.b);
            return temp;
        }
        
        //普通加法函数
        Complex myAdd(Complex &c1, Complex &c2)
        {
            Complex temp(c1.a + c2.a, c1.b + c2.b);
            return temp;
        }
        
    private:
        T a;
        T b;
    };
    
    int main()
    {
        Complex<int> c1(1,2);
        Complex<int> c2(3,4);
        
        Complex<int> c = c1 + c2;
        
        cout<<c<<endl;
        
        return 0;
    }
    
    

    4 内部声明友元模板函数+外部定义友元模板函数

    如果普通的模板函数声明在内的内部,定义在类的外部,不管是否处于同一个文件,就跟普通的函数一样,不会出现任何错误提示。但是如果是友元函数就会出现报错,是因为有二次编译这个机制存在。

    4.1 模板类和模板函数的机制

    在编译器进行编译的时候,编译器会产生类的模板函数的声明,当时实际确认类型后调用的时候,会根据调用的类型进行再次帮我们生成对应类型的函数声明和定义。我们称之为二次编译。同样,因为这个机制,会经常报错找不到类的函数的实现。在模板类的友元函数外部定义时,也会出现这个错误。解决方法是 “ 类的前置声明和函数的前置声明 ”。

    • 按照普通模板函数的样式处理友元函数
    #include <iostream>
    using namespace std;
    
    
    template <typename T>
    class Complex {
        
        //友元函数实现运算符重载
        friend ostream& operator<<(ostream &out, Complex<T> &c);
        
    public:
        Complex(T a, T b);
        
        //运算符重载+
        Complex<T> operator+(Complex<T> &c);
        
        //普通加法函数
        Complex<T> myAdd(Complex<T> &c1, Complex<T> &c2);
        
    private:
        T a;
        T b;
    };
    
    //友元函数的实现
    template <typename T>
    ostream& operator<<(ostream &out, Complex<T> &c)
    {
        out<<c.a << " + " << c.b << "i";
        return out;
    }
    
    
    //函数的实现
    template <typename T>
    Complex<T>::Complex(T a, T b)
    {
        this->a = a;
        this->b = b;
    }
    
    template <typename T>
    Complex<T> Complex<T>::operator+(Complex<T> &c)
    {
        Complex temp(this->a + c.a, this->b + c.b);
        return temp;
    }
    
    template <typename T>
    Complex<T> Complex<T>::myAdd(Complex<T> &c1, Complex<T> &c2)
    {
        Complex temp(c1.a + c2.a, c1.b + c2.b);
        return temp;
    }
    
    
    int main()
    {
        Complex<int> c1(1,2);
        Complex<int> c2(3,4);
        
        Complex<int> c = c1 + c2;
        
        cout<<c<<endl;
        
        return 0;
    }
    
    
    • 友元函数的定义写在类的外部–错误信息
    Undefined symbols for architecture x86_64:
      "operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Complex<int>&)", referenced from:
          _main in demo1.o
    ld: symbol(s) not found for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    

    上面的错误信息,就是典型的二次编译的错误信息,找不到友元函数的函数实现。所以,如果友元模板函数的定义写在函数的外部,需要进行类和函数的前置声明,来让编译器找到函数的实现

    4.2 前置声明解决二次编译问题
    • 类的前置声明
    • 友元模板函数的前置声明
    • 友元模板函数声明需要增加泛型支持

    5 声明和定义分别在不同的文件(模板函数、模板友元)

    类的声明和实现,分别在不同的文件下,需要增加一个hpp文件支持。或者尽量将模板函数与模板友元放在一个文件下。

    • 类的声明与函数的声明写在.h文件
    • 类的实现及函数的实现写在.cpp文件
    • 将.cpp文件改成.hpp文件
    • 在主函数中调用.hpp文件,而不是引用.h文件

    如果碰到.h和.hpp文件都存在的情况下,引用.hpp文件。

    demo2.h文件
    存放类的声明和函数的声明

    #include <iostream>
    using namespace std;
    
    //类的前置声明
    template <typename T>
    class Complex;
    
    //友元函数的声明
    template <typename T>
    ostream& operator<<(ostream &out, Complex<T> &c);
    
    template <typename T>
    class Complex {
        
        //友元函数实现运算符重载
        friend ostream& operator<< <T> (ostream &out, Complex<T> &c);
        
    public:
        Complex(T a, T b);
        
        //运算符重载+
        Complex<T> operator+(Complex<T> &c);
        
        //普通加法函数
        Complex<T> myAdd(Complex<T> &c1, Complex<T> &c2);
        
    private:
        T a;
        T b;
    };
    
    

    demo2.hpp文件
    包括模板函数的实现

    #include "demo2.h"
    
    //友元函数的实现
    template <typename T>
    ostream& operator<<(ostream &out, Complex<T> &c)
    {
        out<<c.a << " + " << c.b << "i";
        return out;
    }
    
    
    //函数的实现
    template <typename T>
    Complex<T>::Complex(T a, T b)
    {
        this->a = a;
        this->b = b;
    }
    
    template <typename T>
    Complex<T> Complex<T>::operator+(Complex<T> &c)
    {
        Complex temp(this->a + c.a, this->b + c.b);
        return temp;
    }
    
    template <typename T>
    Complex<T> Complex<T>::myAdd(Complex<T> &c1, Complex<T> &c2)
    {
        Complex temp(c1.a + c2.a, c1.b + c2.b);
        return temp;
    }
    

    main.cpp文件
    需要调用hpp文件

    #include <iostream>
    using namespace std;
    #include "demo2.hpp"
    
    
    int main()
    {
        Complex<int> c1(1,2);
        Complex<int> c2(3,4);
        
        Complex<int> c = c1 + c2;
        
        cout<<c<<endl;
        
        return 0;
    }
    
    

    更多参考

    展开全文
  • 模板类与类模板、函数模板与模板函数等的区别 函数指针 = 指向函数的指针 指针函数=返回指针的函数 数组指针=指向数组的指针 指针数组=内容是指针的数组 类模板=用来产生类的模板 模板类=使用类模板产生的类...

    模板类与类模板、函数模板与模板函数等的区别

     

    函数指针 = 指向函数的指针

    指针函数=返回指针的函数

    数组指针=指向数组的指针

    指针数组=内容是指针的数组

    类模板=用来产生类的模板

    模板类=使用类模板产生的类

    函数模板=用来产生函数的模板

    模板函数=使用函数模板产生的函数

    后面转至https://www.cnblogs.com/wangduo/p/5559049.html 

     在C++中有好几个这样的术语,但是我们很多时候用的并不正确,几乎是互相替换混淆使用。下面我想彻底辨清几个术语,这样就可以避免很多概念上的混淆和使用上的错误。这几个词是:  

    • 函数指针——指针函数
    • 数组指针——指针数组
    • 类模板——模板类
    • 函数模板——模板函数

      最终在使用中,我们就可以让它们实至名归,名正言顺。  

    1.函数指针——指针函数  

      函数指针的重点是指针。表示的是一个指针,它指向的是一个函数,例子:

      int   (*pf)();  

      指针函数的重点是函数。表示的是一个函数,它的返回值是指针。例子:  

      int*   fun();  

    2.数组指针——指针数组  

      数组指针的重点是指针。表示的是一个指针,它指向的是一个数组,例子:  

      int   (*pa)[8];  

      指针数组的重点是数组。表示的是一个数组,它包含的元素是指针。例子;  

      int*   ap[8];  

    3.类模板——模板类(class   template——template   class)  

      类模板的重点是模板。表示的是一个模板,专门用于产生类的模子。例子:  

    1 template <typename T>
    2 class Vector
    3 {
    4     ...
    5 };

      使用这个Vector模板就可以产生很多的class(类),Vector<int>、Vector<char>、 Vector<   Vector<int>  >、Vector<Shape*>……。  

      模板类的重点是类。表示的是由一个模板生成而来的类。例子:  

      上面的Vector<int>、Vector<char>、……全是模板类。  

      这两个词很容易混淆,我看到很多文章都将其用错,甚至一些英文文章也是这样。将他们区分开是很重要的,你也就可以理解为什么在定义模板的头文件.h时,模板的成员函数实现也必须写在头文件.h中,而不能像普通的类(class)那样,class的声明(declaration)写在.h文件中,class 的定义(definition)写在.cpp文件中。请参照Marshall   Cline的《C++   FAQ   Lite》中的[34]   Container   classes   and   templates中的[34.12]   Why   can't   I   separate   the   definition   of   my   templates   class   from  it's   declaration   and   put   it   inside   a   .cpp   file?   URL地址是http://www.parashift.com/c++-faq-lite/containers-and- templates.html#faq-34.12  

      我将几句关键的段落摘录如下,英文很好理解:  

      In order for the compiler to generate the code, it must see both the  template definition (not just declaration) and the specific types/whatever used to "fill in" the template. For example, if you're trying to use a  Foo<int>, the compiler must see both the Foo template and the fact that  you're trying to make a specific Foo<int>. 

      Suppose you have a template Foo defined like this: 

    复制代码

    1 template<class   T>
    2 class   Foo {
    3 public:
    4     Foo();
    5     void   someMethod(T   x);
    6 private:
    7     T   x;
    8 };

    复制代码

      Along with similar definitions for the member functions:   

    复制代码

     1 template<class   T>
     2 Foo<T>::Foo()
     3 {
     4     ...
     5 }
     6 
     7 template<class   T>
     8 void   Foo<T>::someMethod(T   x)
     9 {
    10     ...
    11 }

    复制代码

      Now suppose you have some code in file Bar.cpp that uses Foo<int>:  

      //   Bar.cpp  

    复制代码

    1 void   blah_blah_blah()  
    2 {  
    3   ...  
    4   Foo<int>   f;  
    5   f.someMethod(5);  
    6   ...  
    7 }    

    复制代码

      Clearly somebody somewhere is going to have to use the "pattern" for the  constructor definition and for the someMethod() definition and instantiate those when T is actually int. But if you had put the definition of the  constructor and someMethod() into file Foo.cpp, the compiler would see the  template code when it compiled Foo.cpp and it would see Foo<int> when it  compiled Bar.cpp, but there would never be a time when it saw both the  template code and Foo<int>. So by rule above, it could never generate the code for Foo<int>::someMethod().  

      关于一个缺省模板参数的例子:  

    1 template   <typename   T = int>
    2 class   Array
    3 {
    4   ...
    5 };

      第一次我定义这个模板并使用它的时候,是这样用的:  

      Array   books;//我认为有缺省模板参数,这就相当于Array<int>   books  

      上面的用法是错误的,编译不会通过,原因是Array不是一个类。正确的用法是Array<>   books;  

      这里Array<>就是一个用于缺省模板参数的类模板所生成的一个具体类。  

    4.函数模板——模板函数(function   template——template   function)  

      函数模板的重点是模板。表示的是一个模板,专门用来生产函数。例子:  

    1 template   <typename   T>  
    2 void   fun(T   a)  
    3 {  
    4   ...
    5 }   

      在运用的时候,可以显式(explicitly)生产模板函数,fun<int>、fun<double>、fun<Shape*>……。  

      也可以在使用的过程中由编译器进行模板参数推导,帮你隐式(implicitly)生成。  

      fun(6);//隐式生成fun<int>  

      fun(8.9);//隐式生成fun<double>  

      fun(‘a’);//   隐式生成fun<char>  

      Shape*   ps   =   new   Cirlcle;  

      fun(ps);//隐式生成fun<Shape*>  

      模板函数的重点是函数。表示的是由一个模板生成而来的函数。例子:  

      上面显式(explicitly)或者隐式(implicitly)生成的fun<int>、fun<Shape*>……都是模板函数。  

      

      关于模板本身,是一个非常庞大的主题,要把它讲清楚,需要的不是一篇文章,而是一本书,幸运的是,这本书已经有了:David   Vandevoorde,   Nicolai   M.   Josuttis写的《C++ Templates:   The   Complete  Guide》。可惜在大陆买不到纸版,不过有一个电子版在网上流传。  

      模板本身的使用是很受限制的,一般来说,它们就只是一个产生类和函数的模子。除此之外,运用的领域非常少了,所以不可能有什么模板指针存在的,即指向模板的指针,这是因为在C++中,模板就是一个代码的代码生产工具,在最终的代码中,根本就没有模板本身存在,只有模板具现出来的具体类和具体函数的代码存在。  

      但是类模板(class   template)还可以作为模板的模板参数(template   template   parameter)使用,在Andrei   Alexandrescu的《Modern   C++   Design》中的基于策略的设计(Policy   based   Design)中大量的用到。  

    1 template<   typename   T,   template<typename   U>   class   Y>  
    2 class   Foo  
    3 {  
    4   ...
    5 };   

      从文章的讨论中,可以看到,名字是非常重要的,如果对名字的使用不恰当的话,会引起很多的麻烦和误解。我们在实际的程序中各种标识符的命名也是一门学问,为了清晰易懂,有时候还是需要付出一定的代价。  

      最后提醒:在本文的几个术语中,语言的重心在后面,前面的词是作为形容词使用的。

    展开全文
  • 这期间有涉及到函数模板与模板函数,类模板与模板类的概念 (类似于类与类对象的区别) 注意:模板类的函数声明和实现必须都在头文件中完成,不能像普通类那样声明在.h文件中,实现在.cpp文件中。 1、函数模板和...
  • 类模板与模板类概念区分

    千次阅读 2019-04-27 09:53:37
    类模板的定义: 允许用户为类定义个一种模式,使得类中的某些数据成员、默认成员函数的参数,某些成员函数的返回值,能够取任意类型 (它是一个参数未确定的模板) template<typename T> class A{}; ...
  • C++类模板与函数模板 & 类模板继承

    千次阅读 2017-04-13 11:39:22
    函数模板与类模板其实就是Java里面的泛型编程,只作为抽象的模板,使用时需要指定具体的类型才能实例 下面就看类模板最典型的案列就能明白了: #include #include #include using namespace std; //类模板 ...
  • C++类模板

    千次阅读 2020-01-27 12:08:20
    C++类模板 模板是C++的高级特性,分为函数模板和类模板。 使用模板能够快速建立里具有类型安全的类库集合和函数集合。 关于函数模板的学习————》》C++函数模板 本文主要介绍类模板。 使用template关键字不但可以...
  • 类模板当作一个类模板的模板参数

    千次阅读 2018-03-24 09:25:08
    #include&...//类模板当作一个类的参数 //设计STL时候用到 //面试,类模板当作参数 class MyClass { public: private: }; template&lt;class T&gt; class MyClass2 { public: T...
  • 写在前面:(模板类是类模板实例化后的一个产物,类模板比作是一个作饺子的模子,而模板类就是用这个模子做出来的饺子,至于饺子什么馅儿的就需要你自己去实例化自己的内容。) 类模板:说明该类是一个模板,它代表...
  • C++ 类模板和模板类

    万次阅读 2015-12-28 20:16:45
    类模板的意义和函数模板的意义是一样的。 类模板的定义 template //声明一个模板,虚拟类型名为T。注意:这里没有分号。 class Compare //类模板名为Compare { public : Compare(T a,T b) { x=a;y=b; } T max( ...
  • 类模板 与 模板类

    千次阅读 2014-09-11 20:46:33
    类模板表示的是一个模板,专门用于产生类的模子。 例如:  template class Example { T a; }; 模板类指的是由一个模板生成而来的类。例如 Example p; Example p; Example p; template class EE :public ...
  • 类模板与模板类

    千次阅读 2013-07-22 12:20:30
    1.类模板与模板类的概念 ⑴ 什么是类模板 一个类模板(也称为类属类或类生成类)允许用户为类定义一种模式,使得类中的某些数据成员、默写成员函数的参数、某些成员函数的返回值,能够取任意类型(包括系统预定义...
  • 类模板和模板类的定义

    千次阅读 2019-05-09 13:03:45
    https://www.cnblogs.com/cxq0017/p/6076856.html 模板类就是在定义函数中参数类型时 定义一个未知类型 而类模板就是在写类的时候定义几个未知参数类型然后进行应用 谢谢上文中的博主 ...
  • 【C++】【模板】类模板和模板类

    千次阅读 2018-09-03 11:02:32
    一、类模板——模板类(class template——template class) 类模板的重点是模板。表示的是一个模板,专门用于产生类的模子。例子: template &amp;lt;typename T&amp;gt; class Vector { ... }; ...
  • 模板之类模板

    2013-08-14 14:17:35
    一:类模板的定义 由于类模板包含类型参数,因此又称为参数化的类。如果说类是对象的抽象,对象是类的实例,则类模板是类的抽象,类是类模板的实例。利用类模板可以建立含各种数据类型的类 eg:vector。 补充:...
  • C++ | 矩阵类模板类模板

    千次阅读 2018-06-22 20:53:08
    问题 B: 矩阵类模板类模板)时间限制: 1 Sec 内存限制: 128 MB提交: 559 解决: 314[提交][状态][讨论版]题目描述设计一个矩阵类模板Matrix,支持任意数据类型的数据。要求至少包含2个成员函数:矩阵转置函数...
  • 1.第一个最简单的类模板案例 #include "mainwindow.h" #include #include #include   templateclass T>  class run { public:   T w;   void show()   { ...
  • IDEA创建类模板和方法模板(超详细)

    万次阅读 多人点赞 2018-08-16 23:54:55
    创建类模板 按照顺序打开File–&gt;settings–&gt;Editor–&gt;File and Code Templates–&gt;Includes 输入类注释模板 /** * @Classname ${NAME} * @Description TODO * @Date $...
  • C++模板、类模板、函数模板详解都在这里了

    千次阅读 多人点赞 2019-07-13 21:45:39
    C++模板、类模板、函数模板详解一、引言二、函数模板1、定义2、调用3、多个虚类型三、类模板1、定义2、调用四、类的函数模板五、类作为数据类型传入六、类模板与继承七、类模板与友元 一、引言 在写排序算法时,如果...
  • 【C++入门】C++ 函数模板&类模板

    千次阅读 多人点赞 2021-02-10 09:52:27
    C++ 函数模板&类模板 主要内容 一、函数模板包括: 1.函数模板的定义 2.函数模板的实例化 3.函数模板的重载 4.函数模板和函数的次序 5.函数模板示例:Map 二、类模板包括: 1.类模板的定义 2.函数模版作为类模板成员...
  • C++ 函数模板&类模板详解

    千次阅读 2018-12-02 16:32:37
    在 C++ 中,模板分为函数模板和类模板两种。函数模板是用于生成函数的,类模板则是用于生成类的。 函数模板&amp;模板函数 类模板&amp;模板类 必须区分概念 函数模板是模板,模板函数时具体的函数 类模板...
  • C++ | 简单类模板(类模板)

    千次阅读 2018-06-25 15:09:52
    简单类模板(类模板)时间限制: 1 Sec 内存限制: 128 MB提交: 498 解决: 346[提交][状态][讨论版]题目描述定义一个列表类,该列表包含属性:数值列表(用长度为100的数组表示),数据长度(实际的数据个数);...
  • C++函数模板与类模板的区别

    万次阅读 多人点赞 2018-07-18 16:54:55
    类模板: C++ 除了支持函数模板,还支持类模板(Class Template)。函数模板中定义的类型参数可以用在函数声明和函数定义中,类模板中定义的类型参数可以用在类声明和类实现中。类模板的目的同样是将数据的类型参数...
  • 类模板三种类模板参数

    千次阅读 2018-04-22 10:40:47
    类模板三种类模板参数 实际上有三种类型模板参数:类型模板参数、模板模板参数(以模板作为模板的参数)、无类型模板参数。 &nbsp; 1、类型模板参数 类型模板参数是我们使用模板的主要目的。我们可以定义多个...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 88,837
精华内容 35,534
关键字:

类模板