C++“模板进阶”相关内容整理分析

1. 非类型模板参数

模板参数分类类型形参与非类型形参。
类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用

注意:

  1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
  2. 非类型的模板参数必须在编译期就能确认结果。

解释和延伸:

  1. 整形常量size_t
  2. 其余的都不可以,即:double, char ,string 等等都不可以
  3. 可以缺省

2. 特化

template<class T1, class T2>
class Data
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};

 //全特化
template<>
class Data < int, char >
{
public:
	Data() { cout << "Data<int, char>" << endl; }
private:
};

// 偏特化
template<class T1>
class Data < T1, char >
{
public:
	Data() { cout << "Data<T1, char>" << endl; }
private:
};

template<class T1, class T2>
class Data < T1*, T2*>
{
public:
	Data() { cout << "Data<T1*, T2*>" << endl; }
private:
};

template<class T1, class T2>
class Data < T1&, T2& >
{
public:
	Data() { cout << "Data<T1&, T2&>" << endl; }
private:
};


template<size_t N>
class A
{
public:
	A(){ cout << "A<N>" << endl; }
};

template<>
class A<10>
{
public:
	A(){ cout << "A<10>" << endl; }

};

int main()
{
	Data<int, int> d1;
	Data<int, char> d2;

	Data<char, char> d3;
	Data<double, char> d4;

	Data<double*, char*> d5;
	Data<char*, char*> d6;

	Data<char&, char&> d7;

	//非类型模板参数的特化 
	A<100> aa1;
	A<10> aa2;

	//  Data<T1, T2>
	//	Data<int, char>
	//	Data<T1, char>
	//	Data<T1, char>
	//	Data<T1*, T2*>
	//	Data<T1*, T2*>
	//	Data<T1&, T2&>
	//	A<N>
	//	A<10>
	return 0;
}

3. 模板的分离编译

什么是分离编译

一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式

.h 文件放函数定义和函数声明
.c/.cpp 放函数定义
为什么这么放?为什么声明和定义要分离?
我们平时写的程序不分离也没事(小的测试程序,学习程序之类的)
在工程和项目中不这样做就会:难以维护,
为什么会难以维护?
想法一:会重复包含。(这个不是问题–》#pragma once)
答:内容太多,相当于目录和内容的区别

声明和定义分离优势是方便维护
.h了解框架设计和基本功能,
.cpp了解具体实现细节

模板的分离编译

模板不支持分离编译

测试代码:

.cpp

#include"vector.h"

void F1(int n)
{
	cout << "void F1(int n)" << endl;
}

//不处理,没有实例化,也没办法编译生成汇编代码
template<class T>
void F2(const T& n)
{
	cout << "void F2(const T& n)" << endl;
}

.h

#include<iostream>
using namespace std;

void F1(int n);

template<class T>
void F2(const T& n);

.cpp

#include"vector.h"

int main()
{
	F1(10);
	F2(10);
	return 0;
}

上述代码编译时(进行模板的分离编译时)会出现,链接错误

1>test.obj : error LNK2019: 无法解析的外部符号 "void __cdecl F2<int>(int const &)" (??$F2@H@@YAXABH@Z),函数 _main 中引用了该符号

链接错误,说明语法的基本检查过了, 找F2的时候找不到,lnk的时候找不到
为什么F1可以F2不可以?
在编译的时候,不知道他的类型是什么,不敢去编译

解决1:

#include"vector.h"

void F1(int n)
{
	cout << "void F1(int n)" << endl;
}

//不处理,没有实例化,也没办法编译生成汇编代码
template<class T>
void F2(const T& n)
{
	cout << "void F2(const T& n)" << endl;
}

//1.显示实例化
template
void F2<int>(const int& n);
//将T实例化成int
//缺陷:你用一个就要显示实例化一个,当你用别的的时候就会出现最开始的报错

解决2:

声明和分离不分离
(有些地方会叫做.hpp)
那么有些地方,头文件展开后,直接就有模板定义和实例化,那么直接就可以填上函数调用地址,不需要链接去找了

为什么放在一个文件里面就会解决这个问题?
因为放在一个文件的话,就不会去链接

4. 模板总结:

优点:

  1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
  2. 增强了代码的灵活性

缺点:

  1. 模板会导致代码膨胀问题,也会导致编译时间变长(实例化过程消耗)
  2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误

延伸:
代码膨胀:会实例化多份,生成的可执行程序变大了
(有人也说这个不是缺点,节省书写)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值