[C++学习日记]-12-模板

模板


函数模板

函数和类有助于使程序更易于编写,更安全,更易于维护。

然而,虽然函数和类确实具有所有这些优点,但在某些情况下,它们也可能受到C++规则的限制,必须为所有参数指定类型。

例如,你可能想写一个函数来计算两个数字的总和,就像这样:

int sum(int a, int b) {
  return a+b;
}

我们现在可以在我们的main中调用两个整型函数。

int main () {
  int x=6, y=16;
  cout << sum(x, y) << endl;
}
// 输出 22

每一个新函数都需要声明类型,比如double型

double sum(double a, double b) {
  return a+b;
}

如果能编写一个能处理任何类型参数的sum()函数,效率会不会更高呢?

函数模板使我们有能力做到这一点!

使用函数模板的基本思想是避免为每个变量指定确切的类型。相反,C ++为我们提供了使用占位符类型(称为模板类型参数)来定义函数的功能。

函数模板的定义

要定义函数模板,请使用关键字template,然后使用template类型定义:

template <class T> 

现在我们可以在函数中使用我们的通用数据类型T:

template <class T> T sum(T a, T b) {
  return a+b;
}

int main () {
    int x=6, y=16;
    cout << sum(x, y) << endl;
}

// 输出 22

该函数返回一个泛型类型T的值,获取的两个参数也是类型T。
其他数据类型可以使用相同的函数,例如double型:

扫描二维码关注公众号,回复: 8669386 查看本文章
template <class T> T sum(T a, T b) {
  return a+b;
}

int main () {
  double x=7.02, y=15.64;
  cout << sum(x, y) << endl;
}
// 输出 22.66

编译器自动调用相应类型的函数。

多个通用数据类型模板

函数模板还可以处理多个通用数据类型。 使用逗号分隔需定义的数据类型。

让我们来创建一个包含多种不同数据类型的参数(一个int和一个double)的函数,然后打印一个较小的值。

template <class T, class U>

正如你所看到的,这个模板声明了两个不同的通用数据类型T和U.

现在我们可以继续我们的函数声明:

template <class T, class U> T smaller(T a, U b) {
  return (a < b ? a : b);
}

(a < b ? a : b)三元运算符用法,检查a<b,如果条件成立返回a,否则返回b

int main () {
  int x=70;
  double y=69.99;
  cout << smaller(x, y) << endl;
}
// 输出 69

最后输出是int型的,应为我们在调用函数模板的时候声明了int型函数。

上述例子中的T仅仅只是一个参数名,type的缩写。在定义参数的时候你可以取一个你自己适用的名字。
 
但是要记住,当你定义了一个模板参数后,你必须在函数定义中使用它,不然编译器会报错。

函数模板总结

  • 函数模板可以节省很多时间,因为它们只写一次,但是可以被不同类型调用。

  • 函数模板减少了代码维护,因为重复代码显着减少。

  • 增强安全性是使用函数模板的另一个优点,因为不需要手动复制函数和更改类型。


类模板

类模板定义

就像我们可以定义函数模板一样,我们也可以定义类模板,允许类使用模板参数的成员作为类型。

使用相同的语法来定义类模板:

template <class T> class Pair {
 private:
  T first, second;
 public:
  Pair (T a, T b):
   first(a), second(b) {
  }
};

就像函数模板一样,您可以使用逗号分隔的列表来定义多个通用数据类型。

类的外部定义成员函数

如果您在类的外部定义成员函数,则需要使用特定的语法,例如在单独的源文件中。

您需要在类名后面的尖括号中指定泛型类型。

例如,要在类的外部定义一个成员函数bigger(),使用以下语法:

template <class T> class Pair {
 private:
  T first, second;
 public:
  Pair (T a, T b):
   first(a), second(b){
  }
  T bigger();
};

template <class T> T Pair<T>::bigger() {
  return (first>second ? first : second);
}

要创建不同类型的模板类的对象,请在尖括号中指定数据类型,就像我们在定义类之外的函数时所做的那样。

在这里,我们为整数创建一个Pair对象。

Pair <int> obj(11, 22);
cout << obj.bigger();
// 输出 22

我们也可以使用相同的类来定义一个double型的对象

Pair <double> obj(23.43, 5.68);
cout << obj.bigger();
// 输出 23.43

模板特化 模板特化

要为数据类型char指定不同的行为,我们将创建一个模板特化。

template <class T> class MyClass {
 public:
  MyClass (T x) {
   cout <<x<<"不是char类型"<<endl;
  }
};

template < > class MyClass<char> {
 public:
  MyClass (char x) {
   cout <<x<<"是char类型!"<<endl;
  }
};

首先,请注意,我们在模板<>的前面添加了一个空的参数列表。 这是因为所有类型都是已知的,并且这个特化不需要模板参数,但是仍然是类模板的特化,因此需要注意这一点。

但比这个前缀更重要的是类模板名称之后的特化参数。 这个特化参数本身标识了模板类被特化的类型(char)。

在上面的例子中,第一个类是通用模板,第二个是特化。

下一步是声明不同类型的对象并检查结果:

int main () {
  MyClass<int> ob1(28);
  MyClass<double> ob2(5.18);
  MyClass<char> ob3('w3cschool');
}
/* 输出: 
28 - 不是char类型
5.18 - 不是char类型
w3cschool 是char类型!
*/

正如你所看到的,泛型模板为int和double所调用。 但是,我们的模板特化是为char数据类型调用的。

请记住,从泛型模板到特化没有成员“继承”,所以模板类特化的所有成员都必须自行定义。


小练习

1.创建一个模板类,内容自定

2.声明三个模板对象对象:i,d,ch,其中i的模板参数是int型,d的模板参数是double型,ch是char型。


上一篇[C++学习日记]-11-抽象、封装、继承和多态

下一篇[C++学习日记]-13-异常处理

发布了20 篇原创文章 · 获赞 14 · 访问量 9032

猜你喜欢

转载自blog.csdn.net/qq_18604209/article/details/104024205