• C++中类模板的概念和意义


    1,在 C++ 中是否能够将泛型的思想应用于类?

        1,函数模板是将泛型编程的思想应用于函数,就有了函数模板;

        2,可以,常用的 C++ 标准库就是 C++ 中的标准模板库,C++ 中的 STL 就是将泛型的思想应用于一系列的函数,就得到了函数模板,当然也有很多的类模板;

        3,类模板就是将泛型思想应用于 C++ 中的类而得到的新概念;

     

    2,类模板:

        1,一些类主要用于存储和组织数据元素;

           1,类模板就是为了数据结构而诞生的;

        2,类中数据组织的方式和数据元素的 具体类型无关;

        3,如:数组类、链表类、Stack 类、Queue 类等;

           1,C++ 中将模板的思想应用于类,使得类的实现不关注数据元素的具体类型,而只关注类所需实现的功能;

          

    3,C++ 中的类模板:

        1,以相同的方式处理不同的类型;

        2,在类声明前使用 template 进行标识;

        3,< typename T > 用于说明类中使用的泛指类型 T;

           1,代码示例:

    1 template < typename T >
    2 class Operator  // class 表明将泛型编程应用于类
    3 {
    4 public:
    5     T op(T a, T b)  // T 在使用类模板定义具体对象的时候关心,其它时候不关心;
    6 };

        4,类模板的应用:

           1,只能显示指定具体类型,无法自动推导;

           2,使用具体类型 < Type > 定义对象;

               1,代码示例:

    1 Operator<int> op1;
    2 Operator<string> op2;
    3  int i = op1.op(1, 20);
    4 string s = op2.op("D.T.", "Software");

                 

    4,类模板:

        1,声明的泛指类型 T 可以出现在类模板的任意地方;

        2,编译器对类模板的处理方式和函数模板相同;

           1,从类模板通过具体类型产生不同的类;

               1,编译器将类模板当做一个模子,这个模子可以产生许多实实在在的类;

           2,在声明的地方对类模板代码本身进行编译;

           3,在使用的地方对参数替换后的代码进行编译;

          

    5,类模板初探编程实验:

    复制代码
     1 #include <iostream>
     2 #include <string>
     3 
     4 using namespace std;
     5 
     6 template < typename T >
     7 class Operator  // 要是用这个类模板有一个前提条件,即当前的 Operator 类模板要操作的数据类型必须支持 +、-、*、/ 这四个运算符,这四个运算符如果要运用于自己定义的数据类型类,要重载这四个运算符;第一次编译是对类模板本身的语法进行编译;
     8 {
     9 public:
    10     T add(T a, T b)
    11     {
    12         return a + b;
    13     }
    14     
    15     T minus(T a, T b)
    16     {
    17         return a - b;
    18     }
    19     
    20     T multiply(T a, T b)
    21     {
    22         return a * b;
    23     }
    24     
    25     T divide(T a, T b)
    26     {
    27         return a / b;
    28     }
    29 };
    30 
    31 string operator-(string& l, string& r)  // 全局函数方式重载 - 操作符,编译通过;先类内部、再全局
    32 {
    33     return "Minus";  // 仅仅为了说明问题;
    34 }
    35 
    36 int main()
    37 {
    38     Operator<int> op1;
    39     
    40     cout << op1.add(1, 2) << endl;  // 3;
    41     
    42     Operator<string> op2;  // 第二次使用类模板时进行编译,但是并不是对所有模板中的函数进行了第二次编译,是分步编译的,首先编译的是构造函数,此时用的是默认的,没有问题,这里编译通过;
    43     
    44     cout << op2.add("D.T.", "Software") << endl;  // D.T.Software;这里编译器针对 add() 函数进行第二次编译;
    45     cout << op2.minus("D.T", "Software") << endl;  // 未有定义全局的重载 - 操作符的函数时,字符串相减没有定义,报错;这里报错展示出来是为了证明类模板编译也是经过了两次编译;这里编译器针对 minus() 函数进行第二次编译;定义全局的重载 - 操作符函数后,打印 Minus ;
    46     
    47     return 0;
    48 }
    复制代码

        1,编译器对类模板第一次编译针对类模板本身代码进行编译;

        2,第二次编译是使用类模板时针对每个成员函数独立编译;

       

    6,类模板的工程应用:

        1,类模板必须在头文件中定义;

        2,类模板不能分开实现在不同的文件中;

        3,类模板外部定义的成员函数需要加上模板 <> 声明;

           1,将类模板的成员函数实现放到类模板的外部实现;

           2,以上三条规则不是 C++ 和编译器的一部分,只是工程应用里习惯这样做,这样做后,代码可维护性、扩展性都会变好,因此建议遵守这三条规则;

     

    7,模板类的工程应用编程实验:

        1,头文件(名字和类名一样) Operator.h 中的内容:

    复制代码
     1 #ifndef _OPERATOR_H_  // 防止被包含两次;
     2 #define _OPERATOR_H_
     3 
     4 template < typename T >
     5 class Operator
     6 {
     7 public:
     8     T add(T a, T b);
     9     T minus(T a, T b);
    10     T multiply(T a, T b);
    11     T divide(T a, T b);
    12 };
    13 
    14 template < typename T >  // 加上类模板;
    15 T Operator<T>::add(T a, T b)  // add() 是 Operator 类模板的;
    16 {
    17     return a + b;
    18 }
    19 
    20 template < typename T >
    21 T Operator<T>::minus(T a, T b)
    22 {
    23     return a - b;
    24 }
    25 
    26 template < typename T >
    27 T Operator<T>::multiply(T a, T b)
    28 {
    29     return a * b;
    30 }
    31 
    32 template < typename T >
    33 T Operator<T>::divide(T a, T b)
    34 {
    35     return a / b;
    36 }
    37 
    38 #endif
    复制代码

     2,头文件的应用;

    复制代码
     1 #include <iostream>
     2 #include <string>
     3 #include "Operator.h"
     4 
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     Operator<int> op1;
    10     
    11     cout << op1.add(1, 2) << endl;  // 3;
    12     cout << op1.multiply(4, 5) << endl;  // 20;
    13     cout << op1.minus(5, 6) << endl;  // -1;
    14     cout << op1.divide(10, 5) << endl;  // 2;
    15     
    16     return 0;
    17 }
    复制代码

          1,三条规则不是硬性要求但是却可以带来很大好处;

       

    8,小结:

        1,泛型编程的思想可以应用于类;

        2,类模板以相同的方式处理不同类型的数据;

        3,类模板非常适用于编写数据结构相关的代码;

        4,类模板在使用时只能显示指定类型;

    此文为作者学习唐佐林老师的学习笔记,仅为交流共享之用,由此带来的后果,与作者无关;转载请注明转载出处;难免有错,欢迎指正,联系方式qunchao24@sina.com。
  • 相关阅读:
    Javascript 匿名函数与闭包
    Javascript 闭包的理解
    Javascript 函数及其执行环境和作用域
    JAVA generic array 泛型数组
    在Ubuntu 13.10 中安装配置 Hadoop 2.2.0
    Java 中文字符判断 中文标点符号判断
    当程序以Windows Services形式启动时当前路径不对
    .NET中Dictionary<TKey, TValue>浅析
    [趣文]单词间那无尽的等待
    DNS拾遗(二)
  • 原文地址:https://www.cnblogs.com/sharecenter/p/14694425.html
Copyright © 2020-2023  润新知