• P1~P2 模板起源


    一、模板起源

    1.1、C++为静态类型语言

    • 这种语言有很多的数据类型(基本类型、类类型),在效率和类型安全性等方面是无可比拟的。

    • 但这种语言在很大程度上也给程序员编写通用代码带来瓶颈。

    • 使程序员不得不为每一种数据类型编写完全相同或近乎完全相同的代码实现,虽然他们在抽象层面是一致的。

    C++具有很多种数据类型,根据数据的特性,采用不同的类型处理,更加安全;但同时也有缺点。

    1.cpp

    # include
    using namespace std;
    
    int max_int(int x, int y){
        return x > y ? x : y;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    此时若想实现两个double类型数据的比较大小还需另写函数:

    double max_double(double x, double y){
        return x > y ? x : y;
    }
    
    • 1
    • 2
    • 3

    main函数调用:

    int main(){
        int nx = 10, ny = 20;
        cout << max_int(nx, ny) << endl;
    
        double dx = 23.3, double dy = 45.8;
        cout << max_double(dx, dy) << endl;
    
        string sx = "world", string sy = "hello";
        cout << max_string(sx, sy) << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    依次类推两个字符串比较大小,还需封装:

    string max_string (string  x, string  y){
        return x > y ? x : y;
    }
    
    • 1
    • 2
    • 3

    数据类型的不一致导致同样的方法需要实现多次。即上述第三点。

    宏可解决此问题。

    1.2、宏可摆脱数据类型的限制

    • 宏是在预处理阶段针对代码的纯文本替换。

    • 宏本身没有函数的语义(不会对数据类型进行检查)

    • 因此借助参数宏虽然可以摆脱类型的约束和限制,但同时也丧失了对数据类型的检查

    2.cpp

    # include
    using namespace std;
    
    # define Max(x, y) (x > y ? x : y)
    
    int main(){
        int nx = 10, ny = 20;
        cout << Max(nx, ny) << endl;
        // 预编译阶段(nx>ny?nx:ny)
    
        double dx = 23.3, dy = 45.8;
        cout << Max(dx, dy) << endl;
        // 预编译阶段(dx>dy?dx:dy)
    
        string sx = "world", sy = "hello";
        cout << Max(sx, sy) << endl;
        // 预编译阶段(sx>sy?sx:sy)
    
        char cx[256] = "world", cy[256] = "hello";
        cout << Max(cx, cy) << endl;
        // 预编译阶段(cx>cy?cx:cy)
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    上述代码中int、double和string类型皆可正常运行,而char时则输出“hello”,预编译阶段(cx>cy?cx:cy)实际是在比较两个指针大小。

    总结:1.cpp函数实现,类型安全,代码冗余,不通用;2.cpp宏实现,代码通用,类型不安全。

    如何实现代码通用,且类型安全?

    1.3、利用宏构建通用函数框架

    • 通过实例化宏,让预处理器将这个宏代换为针对不同数据类型的真正函数。

    • 将宏的通用性和函数的类型安全性完美结合起来。

    3.cpp

    # include
    using namespace std;
    
    //max_##T为函数名,其左边的T为函数返回类型,右边的(T X, T y)为形参表,{}中为函数内部实现;##
    # define MAX(T) T max_##T(T X, T y){\
                         return x > y ? x : y;\
                         }
    MAX(int)
    //预编译纯文本替换,将所有的T替换为int 
    //int max_int(int X, int y){ return x > y ? x : y;}
    MAX(double)
    MAX(string) 
    //同理,将所有的T替换为double、string
    
    
    #define Max(T) max_##T
    int main(){
        int nx = 10, ny = 20;
        cout << Max(int)(nx, ny) << endl;
        // 预编译阶段max_int(nx, ny);
        double dx = 23.3, double dy = 45.8;
        cout << Max(double)(dx, dy) << endl;
        // 预编译阶段max_double(nx, ny);
        string sx = "world", string sy = "hello";
        cout << Max(string)(sx, sy) << endl;
        // 预编译阶段max_string(nx, ny);
    
    
        char cx[256] = "world", cy[256] = "hello";
        cout << Max(string)(cx, cy) << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    max_##T为函数名,其左边的T为函数返回类型,右边的(T X, T y)为形参表,{}中为函数内部实现;##在宏中表示将前面的内容和后边代换出来的内容做拼接。

    3.cpp中程序可实现,但代码可读性低,max_int()、max_double()以及max_string()为预编译器写的函数。

    要提高可读性,调用自己写的函数。

    解决办法:增加一个函数名定义的宏

    #define Max(T) max_##T
    
    • 1

    此时对于char类型,

        char cx[256] = "world", cy[256] = "hello";
        cout << Max()(cx, cy) << endl;
    
    • 1
    • 2

    Max()中的若写为 Max(char*),C++中函数名不允许带*;可写为Max(string),char可给string类型传参。

  • 相关阅读:
    Compiling and Loading
    C/C++程序的内存开辟
    解决Java Heap Space问题的排查与优化方法
    【uniapp】小程序中修改Vant组件navbar左箭头的颜色及图标
    数据结构与算法 -- 子序列问题
    MVMD(多元变分模态分解)
    网络编程day05(IO多路复用)
    2023.11.15 每日一题(AI自生成应用)【C++】【Python】【Java】【Go】 动态路径分析
    SpringBoot+Mybaits搭建通用管理系统实例五:登录健权框架实现上
    服务治理:常用限流算法总结
  • 原文地址:https://blog.csdn.net/qq_37346140/article/details/127680058