当前位置: 首页 > article >正文

C++ 模版★★★

Hello!!大家早上中午晚上好!!今天来复习模版部分知识点!!!

一、什么是模版?

模版是泛型编程的基础 -> 什么是泛型编程?-> 代码复用的一种手段 -> 什么手段? -> 编写与类型无关的通用代码,所以模版就是一段与类型无关的通用代码!

二、什么是函数模版?

模版分两类,一类是函数模版,一类是类模版;
2.1函数模版的定义

函数模版代表了一个函数家族,该函数模版与类型无关,使用时被参数化,根据实参类型生成特定类型的函数;

2.2函数模版语法

template<typename  T1,typename T2,...,typename Tn>

返回类型 函数名(参数列表){}

2.3简单的函数模版
template <typename T>
T Add(T a1, T a2)
{
	return a1 + a2;
}

int main()
{
	int a = 1, b = 2;
	double a1 = 1.2, b1 = 2.2;
	cout<<Add(a, b)<<endl;
	cout << Add(a1, b1) << endl;
	return 0;
}

运行:

2.4模版的实例化:

只要写出通用的函数模版,编译器会根据传入的实参自动实例化出对应参数类型的函数!

2.5显式实例化

上面编译器根据参数类型自动推导出对应的函数,属于隐式实例化;当编译器不能自动推导的时候就需要显式实例化:

当Add传参第一个参数为int,第二个参数为double,且模版参数只有一个的时候,编译器不懂该实例化成int还是double,就会报错;这时有两个方法解决:一是强制类型转换,二是显式实例化

显式实例化(只需要在函数名后加<类型名>):

注意:当参数类型不匹配时,编译器会尝试类型转换,如果转换失败还是会报错!

三、类模版

3.1类模版的定义
template <class T1,class T2,...,calss Tn>
class 类模版名
{
    //类成员
};

简单的类模版:

template <class T>//template(关键字) + <class/typename T(T是根据传入的类型实例化出对应的类型)>
class A
{
public:
	A(T a,T b)
	{
		_a = a;
		_b = b;
	}
	T Add()
	{
		return _a + _b;
	}
private:
	T _a;
	T _b;
};
int main()
{
	A<int> a(3, 5);//显式实例化对象a,并用3,5初始化
	cout << a.Add() << endl;//调用对象a里的成员函数Add()
    A<double> b(3.3, 5.5);
    cout << b.Add() << endl;
	return 0;
}

运行:

3.2类模板的实例化

3.3非类型模版参数

模版参数分类型模版参数和非类型模版参数;

跟在class 或typename 后面的是类型模版参数,没有跟在class或typename后面的是非类型模版参数;

非类型模版参数:必须是常量,必须在编译时就能确定

简单的非类型模版参数:

template <class T,size_t N=20>//T为类型模版参数,size_t N=20为非类型模版参数
class Array
{
public:
	T& operator[](size_t index)
	{
		return _arr[index];
	}
	size_t size()
	{
		return _size;
	}
private:
	T _arr[N];//使用非类型模版参数定义一个静态数组
	size_t size=0;

};

注意:非类型模版参数不能是 浮点型、不能是 类对象、不能是字符串

四、模版的特化

对于某些特殊的类型如果不进行特殊处理会参数错误的结果,这时候就需要模版的特化!!

模版的特化必须要有模版原型才能特化!!

例:两个数比小

4.1函数模版的特化

建议直接写函数就行!

4.2类模版的特化

类模板原形:

template <class T1,class T2>
class A
{
public:
	A(T1 a, T2 b)
	{
		_a = a;
		_b = b;
	}
private:
	T1 _a;
	T2 _b;
};

类模版全特化:

template<>//template 后面+<>
class A<double, double>
{
public:
	A(double a, double b)
	{
		cout << "A(double a,double b)" << endl;
		_a = a;
		_b = b;
	}
private:
	double _a;
	double _b;
};

类模板的半特化:

template<class T1>
class A<T1, double>
{
public:
	A(T1 a, double b)
	{
		cout << "A(T1 a,double b)" << endl;
		_a = a;
		_b = b;
	}
private:
	T1 _a; 
	double _b;
};

类模版的偏特化(针对模版参数更进一步的限制):

//两个参数偏特化为指针类型
template <class T1, class T2>
class A<T1*, T2*>
{
public:
	A(T1* a, T2* b)
	{
		cout << "A(T1* a,T2* b)" << endl;
		*_a = *a;
		*_b = *b;
	}
private:
	T1* _a;
	T2* _b;
};
//两个参数偏特化为引用类型
template <class T1, class T2>
class A<T1&, T2&>
{
public:
	A(T1&a, T2& b)
	{
		cout << "A(T1& a,T2& b)" << endl;
		_a = a;
		_b = b;
	}
private:
	T1& _a;
	T2& _b;
};

测试: 

int main()
{
	int aa = 10;
	int bb = 20;
	A<int, int> a(1, 2);
	A<double, double> b(1.1, 2.2);
	A<int, double> c(11, 22.2);
	A<int*, int*>d(&aa, &bb);
	A<int&, int&>e(aa, bb);
	return 0;
}

运行:

五、模版分离编译

当类模板的声明和定义分离在不同文件时,执行会发生错误

//a.cpp定义
 #define _CRT_SECURE_NO_WARNINGS 1
#include "a.h"
template<class T>
T Add(T a, T b)
{
	return a + b;
}
//a.h声明
#pragma once
template <class T>
T Add(T t1, T t2);
//test.cpp测试调用
#include "a.h"
int main()
{
	cout << Add(1, 2) << endl;
	cout << Add(1.1, 2.2) << endl;
	return 0;
}

运行报错:

原因分析:

因为每个.cpp文件都是分离编译生成各自的.obj文件,编译时,编译器看向.app文件时,没有看到对Add函数模版的实例化,不会实例化出具体的Add函数代码;然后在链接阶段,test.cpp调用了Add函数发生错误!!

解决方法:

声明定义在同一文件中!

#pragma once
//在.h文件内直接定义,不分离
template<class T>
T Add(T a, T b)
{
	return a + b;
}
//test.cpp
#include "a.h"
int main()
{
	cout << Add(1, 2) << endl;
	cout << Add(1.1, 2.2) << endl;
	return 0;
}

好了,今天就复习到这里!!如果您有收获请点赞收藏+关注哦!谢谢!!!

如果您有更好的建议欢迎评论区留言!!

咱下期见!!!


http://www.kler.cn/a/578058.html

相关文章:

  • Android Coil总结
  • c#事件案例与分析
  • 2025年Linux 安全与运维指南
  • 机试题——微服务群组
  • React基础之useCallback
  • LeetCode刷题实战:删除字符串中的所有相邻重复项(栈的经典应用)
  • 2025-03-07 学习记录--C/C++-PTA 习题8-1 拆分实数的整数与小数部分
  • 哪些培训课程适合学习PostgreSQL中级认证知识?
  • CS144 Lab Checkpoint 6: building an IP router
  • 华为欧拉系统 Tomcat 安装详解
  • linux 内网下载 yum 依赖问题
  • ‌CentOS 7.9 安装 Docker 步骤
  • leetcode454 四数相加
  • flutter的debounce_throttle插件使用
  • 进程、线程、锁面试前复习(尽力局)
  • Myslq表的内外连接
  • Python项目-基于Django的在线教育平台开发
  • 【音视频】ffplay简单过滤器
  • 【算法】010、合并两个有序链表
  • 使用 display: flex 实现动态布局:每行两个 item,单数时最后一个占满整行