首页 > 编程语言 >C++语言学习07

C++语言学习07

时间:2023-09-02 17:33:05浏览次数:48  
标签:语言 函数 模版 C++ template 类型 特化 07

一、类型信息运算符
typeid
在C++中typeid可以获取数据的类型,但是需要加头文件 typeinfo
find /usr/include -name typeinfo
1、typeid是运算符,执行运算符函数,执行的返回值类型是type_info
类类型对象
2、type_info中有个name的成员函数
3、type_info中还重载了 == 运算符,可以直接比较两个数据的类型
是否相同
4、它可以区分父类指针或引用指向的是哪个子类,

二、什么是模版
是一种自动生成代码的技术,这种技术能让程序员在编写代码时不需要考虑
数据类型,因此也称为泛型编程技术

三、为什么要使用模版
1、C/C++/JAVA/C# 属于静态编程语言(编写->预处理->编译->汇编->链接->可执行文件)-强类型语言,
静态编程语言优点是运行速度快,缺点代码改动后重新编译、实现代码的通用比较麻烦
javascript/Python/shell 弱类型语言 动态编程语言(运行速度要慢,但是不需要生成文件,可以直接运行)

C语言实现一个通用的快排
2、C语言中的通用类型是通过void* +回调函数实现的,实现难度大,使用比较麻烦
3、借助定义宏的方式实现代码通用,但是宏有一定的缺点:类型不检查,没有返回值、二义性等问题
4、借助函数重载也可以实现函数代码的通用,可能会导致代码段增多,无法解决未知类型
5、综上所诉,C++之父为了解决代码通用问题,实现了模版技术,让C++摆脱数据类型的困扰

三、函数模版
1、函数模版的定义
template
void func(T num)
{

    }
    未知类型名可以取任意名字,一般约定T

2、函数模版的原理
    函数模版会经历两次编译
    a、检查函数模版的语法是否有错误,如果无误也不生成函数的二进制
    指令,代码段没有存储该函数模版
    b、根据调用者提供的实参类型再次编译检查函数模版代码,如果也没有
    错误,才会生成一份二进制指令存储在代码段中,所以,如果函数模版没
    有任何一次调用则不会生成任何二进制指令,如果有不同类型的实参调用
    函数模版,则会生成另一份二进制指令存储在代码段
    这种函数模版实例化称为"惰性实例化"准则

3、函数模版的调用
    C++编译器不会把函数模版当作一个函数实体,而是当作生成函数实体的工具,
    当调用函数模版并提供了实际类型参数后,才会生成函数实体
    
    调用函数模版必须提供相应数量的类型参数
    自动:编译器会自动根据实参的类型,获取函数模版的类型
    手动:函数名<type1,type2,...>(实参)会根据<>中提供的类型名去生成
    函数实体

4、默认形参类型
    template<typename T1,typename T2=int,typename T3=long>
    T3 函数名(T1 arg1,T2 arg2)
    {
        T3 ret = arg1+arg2;
        return ret;
    }
    函数模版的类型参数可以像普通函数的默认形参设置形参值一样去设置默认的
    形参类型。靠右原则一致,但是该语法只有C++11后才支持

    支持-std=gun++0x

5、函数模版的特化
    模版虽好但是不能直接解决所有类型的问题,有一些特殊类型与普通类型的运算
    规则不同,例如char* ,因此需要给这些特殊类型实现一个特殊版本,这种称为
    函数模版的特化
    特化的方式:
        1、通过typeid()分支判断类型执行特殊步骤
            if(typeid(T) == typeid(char*))
        2、实现一个特化的版本
        特化的格式
            template<>
            特化类型返回值 函数名(特化类型 形参名){}
    注意:
        1、特化前,必须有一个基础版本的函数模版
        2、template<>一定要加,才说明是函数模版的特化
        3、特化函数的形参基础类型要与函数模版的形参基础类型相同,否则
        报错,例如函数模版中有引用,特化中也需要有
        4、编译器会优先调用函数模版中的特化版本,因此不会与基础的函数模版冲突
        5、可以同时存在类型完全相同的普通函数、函数模版的特化、函数模版,按照普通
        ->特化->函数模版 的顺序调用
        6、普通函数无论是否被调用都会生成二进制指令,但是模版特化依然遵循"惰性实例化"
        准则,不被调用时不生成二进制指令

四、类模版
使用未知类型来设计类类型
1、类模版定义
tempname<typename T1,typename T2>
class 类名
{
T1 成员变量;
public:
T2 func(void)
{
T2 ret;
return ret;
}
};

2、类模版的使用
    类模版必须先实例化才能使用,与函数模版不同的是不支持自动实例化,
    只能显式提供类型参数手动实例化
    类名<类型参数>  对象名;
    类名<类型参数>* 对象指针 = new 类名<类型参数(构造函数的实参数);

练习:实现链式队列的类模版

3、类模版中的静态成员
    类模版中允许有静态成员,与普通类的静态成员变量一样需要在类外定义
    template<typename T>
    class 类名
    {
        static 类型名 num;
    };
    template<typename T> T 类名<T>::num = 初始数据;
    对于每个类模版实例化出来的类对象,也是共享静态成员变量

4、递归实例化
    什么类型都可以是模版的类型参数,包括类模版类型
    template<typename T>
    class A
    {
        T a;
    };

    template<typename T>
    class B
    {
        T b;
    };
    
    B<A<int>> b;    //  C++11之后才允许
    B<A<int> > b;   //  C++11之前必修加空格

5、类模版的默认参数类型
    与函数模版的默认参数类型规则一样
    template<typename T=类型名>
    class A
    {
        T a;
    };

6、类模版的局部特化
    当类模版中的成员函数不能支持所有类型时,可以针对不同类型实现类模版中的
    成员函数的特化版本,称为类模版的局部特化
    方法1:通过typeid比较类型,通过分支语句执行特殊操作
    方法2:通过实现局部特化成员函数来处理

    template<>
    int List<const char*>::find(const char* const& data)

    注意:
    1、一般在类外实现局部特化
    2、类型名的格式除了替换的typename 的类型发生替换,其余所有格式都需要一致
    ,例如常属性、引用等


7、类模版的全局特化
    为特殊类型重新特化一个类模版,称为类模版的全局特化
    template<>
    class 类名<特殊类型>
    {
        重新实现类
    }

标签:语言,函数,模版,C++,template,类型,特化,07
From: https://www.cnblogs.com/c-learnmore/p/17673949.html

相关文章

  • linux C++ UDP
    1.UDP与TCP差异:注意:UDP不同于TCP,没有请求连接过程connect()与受理过程accpet(),因此无法区分客户端与服务器端。TCP与UDP差异仅仅在于TCP存在在不可靠IP层的流控制机制,所以TCP可以提供可靠数据服务,形象化的比喻就是TCP相当于打电话,而UDP相当于信封,电话得先建立一个可靠的信道,再......
  • c++编译
    1.1c++编译c++脚本程序写完之后,并不能直接运行,需要进行编译,转成.o文件,再链接才能运行,一般包括:预处理,汇编,编译。链接四步,如下:预编译把.c源文件编译成.ii预处理文件gcc-E[源文件.c]-o[自定义名.ii]编译成汇编语言把.i文件编译成.s汇编语言文件gcc-S[......
  • 学生信息管理系统代码分享 - C语言控制台程序
    【代码要求】   设计与实现学生信息管理系统,实现对学生信息的管理,并且学生的学号是代表该学生信息的唯一性标志。另外学生信息包括:学号、姓名、性别、班级、身份证号、出生日期、联系方式。   该系统具有以下几个功能:   1.系统界面美观、简洁,采用菜单式显示......
  • 学生信息管理系统代码分享 - C语言控制台程序
    【代码要求】   设计与实现学生信息管理系统,实现对学生信息的管理,并且学生的学号是代表该学生信息的唯一性标志。另外学生信息包括:学号、姓名、性别、班级、身份证号、出生日期、联系方式。   该系统具有以下几个功能:   1.系统界面美观、简洁,采用菜单式显示......
  • C++程序的内存模型--模型四区
      C++中在程序运行前分为全局区和代码区 代码区特点是共享和只读 全局区中存放全局变量、静态变量、常量 常量区中存放const修饰的全局变量和字符串常量 //栈区//由编译器自动分配释放、存放函数的参数值、局部变量等//注意:不要返回局部变量的地址,栈区开辟的数据由编译器......
  • linux开发C/C++
    最近在部署项目的时候总是会遇到关于C++的编译问题,由于之前学习C++只是为了参加算法竞赛,缺少这一部分的知识,所以学习一下这一相关内容,并做一下记录参考:VSCode开发C++七讲【基于VSCode和CMake实现C/C++开发|Linux篇】https://www.bilibili.com/video/BV1fy4y1b7TC?p=17&vd_sourc......
  • P1463 [POI2001] [HAOI2007] 反素数 题解
    P1463[POI2001][HAOI2007]反素数题解可以发现,最大的不超过\(n\)的反素数就是\(1\simn\)中因数最多的数字。证明:设\(x,x\in[1,n]\)为\(1\simn\)中因数最多的数字,则\(x<y\len\)都不会成为答案,因为存在\(x<y\)因数比\(y\)多,同时也不会存在\(y'<x\)......
  • 东方博宜OJ1007 统计大写字母的个数 C语言版
    题目描述算算以'.'结束的一串字符中含有多少个大写的英文字母。输入输入一串字符(长度不超过 8080 ),以'.'结束。输出输出一行,即这串字符中大写字母的个数。样例输入PRC,PRC,I'mfromChina.输出8来源字符串代码#include<stdio.h>intm......
  • C语言生成随机数问题
    (C语言生成随机数问题)rand函数rand-C++Reference(cplusplus.com)rand()函数是专门用来生成随机数的rand()返回的是0~RAND_MAX(32767)之间的随机数rand()函数在头文件stdlib.h中,使用前要导入这个头文件因为rand默认生成随机数范围是0~32767,这是一段很大的范围,所以我们需......
  • 东方博宜OJ 打印星号三角形 C语言版
    题目描述打印星号三角形。输入输入只有一行,包括 11 个整数 n , n 代表行数。输出输出 n 行。样例输入5输出************************************************************************......