cpp 模板函数,类模板(1)


对应《c++ primer 第五版》的第16章前半部分,这里是一个简单的总结。

为了防止对每个不同的类型都定义一个函数,可以使用通用的模板,一个函数模板就是一个公式,可用来生成针对特定类型的函数版本。

模板定义以template开始,后面跟一个模板参数列表,用< >括起来。 模板定义中,模板参数列表不能为空。

模板参数列表就像函数的参数列表一样,在运行时要用实参来初始化形参。 当使用模板时,显式或隐式地指定模板实参,将其绑定到模板参数上。 比如定义了一个模板函数compare

template<typename T> 
int compare(const T &v1, const T &v2)

使用时,如果这样用

compare(1, 0)

就相当于instance化了一个特定版本的函数,T绑定了int。

声明为inline或者constexpr的,inline这个关键字要放在模板参数列表之后,返回类型之前,如下

template <typename T> inline T min(const T&, const T&)

类型参数前必须使用关键字class 或 typename, 可以看到上面都用的是typename, 也可以用

template <class T>

因为typename是在模板已经广泛使用之后才引入cpp语言中的,所以一些程序员仍然只用class

每个类型参数前必须使用class 或者 typename, 下面这样做是不对的

template <typename T, U>  //这样不对,U前也必须用typename 或 class

说下模板的编译:

编译器遇到一个模板定义时,并不生成代码,只有当实例化时才会生成代码。 大多数编译错误是在实例化期间报告的 第 1 阶段编译模板本身时,会检查语法错误,比如忘记分号。 第 2 阶段 编译器遇到模板使用时,对函数模板的调用,会检查实参数目是否正确。 第 3 阶段实例化时,只有这个阶段才能发现类型相关的错误,这类错误可能在link时才报告。

类模板:

类模板也是以关键字template开始,后面跟模板参数列表

template <typename T> class Blob {
          
   
    ...
};

这里要说下阅读模板类代码时,要记住类模板的名字不是一个类型名,比如

template<class SEMANTICS>
bool SemanticsOcTreeNode<SEMANTICS>::isSemanticsSet() const
{
          
   
  return this->semantics.isSemanticsSet();
}

SEMANTICS semantics;

可以看到isSemanticsSet函数是semantics对象的函数,但是要知道SEMANTICS并不是一个类型名,它具体是什么类型,要看调用它的地方传的是什么实参类型。

和其他类相同,既可以在类模板内部,也可以在类模板外部定义其成员函数。 且定义在类模板内的成员函数被隐式声明为inline函数。

为了生成一个实例化版本,编译器需要掌握函数模板或类模板成员函数的定义,因此,函数模板和类模板成员函数的定义通常放在头文件中。

在类模板自己的作用域中,可以直接使用模板名而不提供实参,如下

template <typename T> class B {
          
   
   ...
   B& operator++();  //这里不需要指定B<T>
};

但是,当定义在类模板外时,就要加上

friend class

如果模板类包含一个非模板friend class, 那么友元被授权可以访问所有模板实例, 如果友元自身是模板,类可以授权给所有友元模板实例,也可以只授权给特定实例。 具体下次再码。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/290323.html

(0)
上一篇 2022年10月2日
下一篇 2022年10月2日

相关推荐

发表回复

登录后才能评论