zoukankan      html  css  js  c++  java
  • C++泛型编程:template模板

    泛型编程就是以独立于任何特定类型的方式编写代码,而模板是C++泛型编程的基础.

    所谓template,是针对“一个或多个尚未明确的类型”所编写的函数或类.

    使用template时,可以显示的或隐示的将类型当作参数来传递.

    下面是一个典型的例子,传回两数中的较大者:

    template<class T>
    inline const T& MAX(const T& a,const T& b)
    {
       return a>b?a:b;
    }

    在这里,第一行将T定义为任意数据类型,于函数被调用时由调用者指定.

    这个类型有关键字class引导,也可用typename引导,typename其实比class更直观.

    (需要注意的是,如果用到了嵌套依赖类型,则必须要用到typename).

    理解:

      第一行template<class T>告诉编译器:我在这儿定义了一个可变类型T,调用者使用什么类型你就怎么编译吧!

    缺省模板参数

    template class可以有缺省参数,例如一下声明,允许你使用一个或多个template来声明MyClass对象:

    template<class T,class container=vector<T> >
    class MyClass
    {
    public:
         MyClass(){}
         ~MyClass(){}
    protected:
    private:
    };

    如果只传递一个参数,那么缺省参数可作为第二参数使用:

    MyClass<int> x1; // equivalent to:
    MyClass<int,vector<int> > x2;

    注意:template缺省参数根据前一个(或前一些)参数而定义。这也就意味着如果参数传递列表中某个参数是缺省参数,那么后面的所有参数都应该是缺省参数.

    关键字typename

    关键字typename被用来做为类型之前的标识符号。考虑下面例子:

    template<class SubType>
    struct BaseType
    {
         SubType a;
    };
    
    template <class T>
    class MyClass1
    {
         typename T::SubType *ptr;
         // ...
    };

    这里,typename指出SubType是class T中定义的一个类型,因此ptr是一个指向T::SubType的指针.

    如果没有typename,SubType将会被当成一个static成员,于是:

    T::SubType * ptr;

    会被解释为类型T中的两个子成员SubType和ptr的乘积.

    成员模板

    class成员函数可以是个template,但是这样的成员template类型既不能是virtual,也不能有缺省参数,例如:

    class MyClass
    {
         //...
         template<class T>
         void f(T);
    };

    在这里,MyClass::f声明了一个成员函数,适用于任何类型参数.

    这个特性常用来为template class中的成员提供自动类型转换,例如下面的例子中,assign()的参数x,其类型必须和调用端所提供的对象的类型完全吻合:

    template<class T>
    class MyClass
    {
    public:
         MyClass();
         ~MyClass();
         void assign(const MyClass<T>& x) // x must have same type as *this
         {
               value=x.value;
         }
         // ...
    protected:
    private:
         T value;
    };

    如果使用了两个类型,即使两个类型之间可以自动转换,也会出错:

    void fun()
    {
         MyClass<double> d;
         MyClass<int> i;
    
         d.assign(d); // OK
         d.assign(i); // ERROR: i is MyClass<int> but MyClass<double> is required
    }

    理解:

      对于一个template class中的template成员,遵循“先入为主”,如果第一次指定了类型,那么后面都要和第一次保持一致.

    但如果要指定两个不同类型的类成员变量怎么办呢?

    方法很简单,我们将成员变量在使用一个和class不同的template类型就行:

    template<class T>
    class MyClass
    {
    public:
         MyClass();
         ~MyClass();
         template<class X> // member template
         void assign(const MyClass<X>& x) // allow different template types
         {
               value = x.getValu();
         }
         T getValue() const
         {
               return value;
         }
         // ...
    protected:
    private:
         T value;
    };
    
    void fun()
    {
         MyClass<double> d;
         MyClass<int> i;
         
         d.assign(d); // OK
         i.assign(i); // OK (int is assigned to double)
    }
  • 相关阅读:
    四,iptables详解(4):iptables匹配条件总结之一
    三,iptables详解(3):iptables规则管理
    二,iptables详解(2):iptables实际操作之规则查询
    一,Iptables详解(1):iptables概念
    运维安全之Linux网络安全(iptables)
    【577】U-Net相关
    【576】Python遍历文件夹内所有文件
    【575】连续卷积层(神经网络中的通道 channel)
    【574】KDE与正态分布
    点云投影为深度图
  • 原文地址:https://www.cnblogs.com/crazyacking/p/4997425.html
Copyright © 2011-2022 走看看