2021-04-22

c++学习-- 类模板 0.1

  • 一个类模板允许用户为类定义一种模式,使得类中的某些数据成员、默写成员函数的参数、某些成员函数的返回值,能够取任意类型(包括系统预定义的和用户自定义的)。
  • c++中 类模板 的引入是为了提高代码的重用性。模板是创建泛型类或函数的蓝图或公式。继承(公有、私有或保护)和包含并不总是能够满足重用代码的需要。容器类设计用来存储其他对象或数据类型。可以定义专门用于存储double值或string对象的Stack类。然而,与其编写新的类声明,不如编写一个泛型(即独立于类型的)栈,然后将具体的类型作为参数传递给这个类。这样就可以使用通用的代码生成存储不同类型值的栈。
  • C++的类模板为生成通用的类声明提供了一种更好的方法。模板提供参数化(parameterized)类型,即能够将类型名作为参数传递给接收方来建立类或函数。
  1. 类模板 vs 模板类

类模板是模板,而模板类是具体的类。由函数模板实例化而得到的函数称为模板函数。由类模板实例化得到的类叫模板类。

1.1. 定义类模板

template意思是“模板”,该关键字告诉编译器,将要定义一个模板。在template后面的尖括号内的内容为模板的参数表列,关键字class(也可以用typename)表示其后面的是类型参数。在建立类对象时,如果将实际类型指定为int型,编译系统就会用int取代所有的T,如果指定为float型,就用float取代所有的T。这样就能实现“一类多用”。

  1. 关键字class vs typename

使用class并不意味着Type(T)必须是一个类;而只是表明Type(T)是一个通用的类型说明符,在使用模板时,将使用实际的类型替换它。较新的C++实现允许在这种情况下使用不太容易混淆的关键字typename代替class

template <typename T> //声明一个模板,虚拟类型名为T。注意:这里没有分号。
class GrainDataTracker : public GrainTracker //类模板名为GrainDataTracker
{
public:
  const T & getData(unsigned int grain_id) const;

protected:
  virtual T newGrain(unsigned int new_grain_id) = 0;

};

template <typename T>
const T &
GrainDataTracker<T>::getData(unsigned int grain_id) const
{
  mooseAssert(grain_id < _grain_data.size(), "Requested data for invalid grain index.");
  return _grain_data[grain_id];
}

1.2. 使用模板类

类模板的使用实际上是将类模板实例化成一个具体的类,它的格式为:类名<实际的类型>。即需要声明一个类型为模板类的对象,方法是使用所需的具体类型替换泛型名。模板类是类模板实例化后的一个产物。说个形象点的例子吧。我把类模板比作一个做饼干同的模子,而模板类就是用这个模子做出来的饼干,至于这个饼干是什么味道的就要看你自己在实例化时用的是什么材料了,你可以做巧克力饼干,也可以做豆沙饼干,这些饼干的除了材料不一样外,其他的东西都是一样的了。

class GrainTrackerElasticity : public GrainDataTracker<RankFourTensor>
{
public:
  static InputParameters validParams();


protected:
  RankFourTensor newGrain(unsigned int new_grain_id);

};

泛型标识符——例如这里的Type——称为类型参数(type parameter),这意味着它们类似于变量,但赋给它们的不能是数字,而只能是类型。
类型参数可以有一个或多个,修改GrainDataTracker,成为template <typename T1,typename T2>

1.3. 类模板与派生

  1. 类模板从普通类中派生
template <typename T> //声明一个模板,虚拟类型名为T。注意:这里没有分号。
class GrainDataTracker : public GrainTracker //类模板名为GrainDataTracker
{
public:

protected:
};
  1. 普通类从类模板中派生类
class GrainTrackerElasticity : public GrainDataTracker<RankFourTensor>
{
public:

protected:

};
  1. ……

1.4. 使用多个类型参数

模板可以包含多个类型参数。例如,假设希望类可以保存两种值,则可以创建并使用类模板来保存两个不同的值。

1.5. 模板声明与定义都在头文件内

通常情况下,你会在.h文件中声明函数和类,而将它们的定义放置在一个单独的.cpp文件中。但是在使用模板时,这种习惯性做法将变得不再有用,因为当实例化一个模板时,编译器必须看到模板确切的定义,而不仅仅是它的声明。因此,最好的办法就是将模板的声明和定义都放置在同一个.h文件中。这就是为什么所有的STL头文件都包含模板定义的原因。

1.6. 类模板的作用

模板是泛型编程的基础,所谓泛型编程就是用独立于任何特定类型的方式编写代码。类是对象的抽象,而模板又是类的抽象,也就用模板能定义出具体类。

在c++里,常说的多态一般分为两种:

  • 一种是运行时的多态,也就是虚函数体现的多态
  • 另一种是编译时的多态,也就是泛型编程的多态,体现在参数的多态

1.7. 参考

  1. 《C++ Primer Plus》
  2. c++ 类模板和模板类的深入解析
  3. C++ 模板常见特性(函数模板、类模板),知乎这篇文章讲的非常详细。
  4. 模板声明与定义要放在同一文件中?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值