【C++】_5.模板

2023-11-19

目录

1.泛型编程

2.函数模板

2.1 概念

2.2 函数模板格式

2.3 函数模板原理

2.4  函数模板的实例化

2.5 函数模板的匹配原则

3.类模板

4.非类型模板参数

5.模板的特化

5.1 概念

5.2 函数模板特化

5.3 类模板特化

6.模板分离编译

6.1  分离编译模式

6.2 模板的分离编译

6.3 解决方法



1.泛型编程

void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
}
void Swap(double& left, double& right)
{
	double temp = left;
	left = right;
	right = temp;
}
int main()
{
	int i = i, j = 2;
	double x = 1.1, y = 2.2;
	Swap(i, j);
	Swap(x, y);
	return 0;
}

相比C语言,C++的引用、函数重载等等已经为代码的书写提供了很大遍历,但仍然存在问题:

如上文代码,函数重载面对新类型的对象需要不断创建同名且逻辑类似的函数,这是非常重复且低效的。

故而C++引入泛型编程:

编写与类型无关的通用代码,是代码复用的一种手段。而模板是泛型编程的基础。

模板又分为函数模板和类模板;

2.函数模板

2.1 概念

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

2.2 函数模板格式

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

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

template<typename T>  
//template<class T>
void Swap(T& left, T& right)
{
	T tmp = left;
	left = right;
	right = tmp;
}
int main()
{
	int i = 1, j = 2;
	double x = 1.1, y = 2.2;
	char m = 'A', n = 'B';
	Swap(i, j);
	Swap(x, y);
	Swap(m, n);
	
	cout << "i=" << i << ",j=" << j << endl;
	cout << "x=" << x << ",y=" << y << endl;
	cout << "m=" << m << ",n=" << n<< endl;
	return 0;
}

说明: ① 模板参数类似于函数参数,只是模板参数是模板类型,函数参数是参数对象;

② typename后的T自由定义,通常用单词首字母大写;

③ T表示一个模板类型(虚拟类型);

④ 此处template<typename T>可以用template<class T>替换;

2.3 函数模板原理

以上文代码为例,基于先前所学知识,我们知道在函数体内创建的临时变量tmp基于T的不同,字节也不同,而函数调用时建立栈帧也会因此不同,因此调用的三个函数必然是不同的函数;

可用反汇编来验证:

 其实函数模板就是把程序员要做的事交给了编译器:
在编译阶段:编译器会根据传递的实参类型来推演生成对应类型的函数以供调用

2.4  函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。

模板实例化分为显式实例化和隐式实例化。

2.4.1 隐式实例化:编译器根据实参类型推演模板参数的实际类型

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	Add(1, 2);
	Add(1.1,2);
	return 0;
}
//实参类型不同导致的实例化链接错误

如果实参为多种类型,仍然想创建函数模板,可以进行如下操作:

(1)强转

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	Add(1, 2);
    //强转
	Add((int)1.1, 2);     //输出结果为3
	Add(1.1,(double)2);   //输出结果为3.1
	return 0;
}
//此种方法可能造成精度丢失,可能得不到预期输出

(2)多参数:

template<class T1,class T2>
T1 Add(const T1& left, const T2& right)
{
	return left + right;
}
int main()
{
	cout << Add(1.2, 2) << endl;
	return 0;
}
//返回值较麻烦,不建议使用

(3)进行显式实例化:

2.4.2 显式实例化:

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	cout<<Add(1, 2)<<endl;
	//显式实例化
	cout << Add<int>(1.1, 2) << endl;    //输出结果为3
	cout << Add<double>(1.1, 2) << endl; //输出结果为3.1
	return 0;
}

2.5 函数模板的匹配原则

一个非模板函数和一个同名的模板函数同时存在,该函数模板还可以被实例化为这个非模板函数:

//函数模板
template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
//专门处理int的加法函数
int Add(int left, int right)
{
	return left + right;
}

int main()
{
	cout<<Add(1, 2)<<endl;
    return 0;
}

并且,编译器匹配参数类型时会先调用参数类型匹配的函数

当不存在参数类型匹配的函数时,才会调用函数模板进行实例化;

3.类模板

以栈为例:

template<typename T>
class Stack
{
public:
	Stack(size_t capacity = 0)
		:_a(nullptr)
		,_capacity(0)
		,_top(0)
	{
		if (capacity > 0)
		{
			_a = new T[capacity];
			_capacity = capacity;
			_top = 0;
		}
	}
	~Stack()
	{
		delete[] _a;
		_a = nullptr;
		_capacity = _top = 0;
	}
	void Push(const T& x);
	void Pop()
	{
		assert(_top > 0);
		--_top;
	}
	bool Empty()
	{
		return _top == 0;
	}
	const T& Top()    //防止栈中数据被修改
	{
		assert(_top > 0);
		return _a[_top-1];
	}
private:
	T* _a;
	size_t _top;
	size_t _capacity;
};
template<typename T>
void Stack<T>::Push(const T& x)
{
	if (_top == _capacity)
	{
		//1.开新空间
		//2.拷贝数据
		//3.释放旧空间
		size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
		T* tmp = new T[newcapacity];
		if (_a)
		{
			memcpy(tmp, _a, sizeof(T) * _top);
			delete[] _a;
		}
		_a = tmp;
		_capacity = newcapacity;
	}
	_a[_top] = x;
	++_top;
}
//模板不支持分离编译,即不支持声明放在.h文件中,定义放在.cpp文件中;
//但在同一个文件中,模板支持声明与定义分离;
int main()
{
	try
	{
		类模板都是显式实例化
		//Stack<int> st1;  //char
		//Stack<char> st2;  //int
		虽然使用了一个类模板,但是是不同的类型
		Stack<int>st1;
		st1.Push(1);
		st1.Push(2);
		st1.Push(3);
		st1.Push(4);
		st1.Push(5);
		while (!st1.Empty())
		{
			cout << st1.Top() << " ";
			st1.Pop();
		}
		cout << endl;
	}
	catch (const exception& e)
	{
		cout << e.what() << endl;
	}
	return 0;
}

4.非类型模板参数

模板参数分为类型形参和非类型形参:
类型形参:出现在模板参数列表中,跟在class或typename之类的参数类型名称;

非类型形参:用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用; 

以静态数组类为例:

template<class T,size_t N=10>  //可提供缺省值
//template<class T,size_t N>
//N是非类型模板参数,是一个常量
class array
{
private:
	T _a[N];
};
int main()
{
	array <int>a0;
	array <int, 100>a2; //100
	array <double,1000>a2;  //1000
	return 0;
}

PS:(1)浮点数、类对象以及字符串是不允许作为非类型模板参数的,一般情况下费类型模板参数都是整型;

(2)非类型的模板参数必须在编译期就能确认结果;

PS:array类的介绍:

 对于array<int,10>a1和a2[10]的区别:

对于a2来说,C++对静态数组的检查是数组长度后的某些特定位置进行抽查,而a2元素的访问是指针解引用,一般情况下,类似于a2[10]这样的越界读是不会被抽查到的,a2[10]=0这样的越界可能会被抽查出来;

而对于array<int,10>a1来说,其元素访问是通过函数调用,会对访问元素的下标进行检查,所以只要是越界,都会检查出来;

5.模板的特化

5.1 概念

模板的特化就是在原有模板的基础上,针对某些类型进行特殊化处理;

struct Date
{
    Date(int year, int month, int day)
        :_year(year)
        , _month(month)
        , _day(day)
    {}
    int _year;
    int _month;
    int _day;
    bool operator>(const Date& d)const
    {
        if ((_year > d._year)
            || (_year == d._year && _month > d._month)
            || (_year == d._year && _month == d._month && _day > d._day))
        {
            return true;
        }
        else
            return false;
    }
};
template<class T>
bool Greater(T left, T right)
{
    return left > right;
}
int main()
{
    cout << Greater(1, 2) << endl;

    Date d1(2022, 7, 7);
    Date d2(2022, 7, 8);
    cout << Greater(d1, d2) << endl;

    Date* p1 = &d1;
    Date* p2 = &d2;
    cout << Greater(p1, p2) << endl;
}

 对上文代码,当实参为指针时,会进行实参地址大小的比较,并无意义,我们希望当传递欲比较对象的地址时,仍然可以进行对象本身大小的比较,故而需要对Greater函数进行特例化,当形参为对象指针时,也进行对象的大小比较而非对象指针大小的比较;

5.2 函数模板特化

基于上文代码,进行Greater函数的特化:

struct Date
{
    Date(int year, int month, int day)
        :_year(year)
        , _month(month)
        , _day(day)
    {}
    int _year;
    int _month;
    int _day;
    bool operator>(const Date& d)const
    {
        if ((_year > d._year)
            || (_year == d._year && _month > d._month)
            || (_year == d._year && _month == d._month && _day > d._day))
        {
            return true;
        }
        else
            return false;
    }
};
template<class T>
bool Greater(T left, T right)
{
    return left > right;
}
template<>
bool Greater<Date*>(Date* left, Date* right)
{
    return *left > *right;
}
int main()
{
    cout << Greater(1, 2) << endl;

    Date d1(2022, 7, 7);
    Date d2(2022, 7, 8);
    cout << Greater(d1, d2) << endl;

    Date* p1 = &d1;
    Date* p2 = &d2;
    cout << Greater(p1, p2) << endl;
}

增加特化函数后,当实参为对象指针时,自动调用参数为指针的函数,比较对象本身的大小;

5.3 类模板特化

基于以上代码:

#include<queue>
#include<list>
#include<vector>
struct Date
{
	Date(int year,int month,int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{}
	int _year;
	int _month;
	int _day;

	bool operator<(const Date& d)const
	{
		if ((_year < d._year)
			|| (_year == d._year && _month < d._month)
			|| (_year == d._year && _month == d._month && _day < d._day))
		{
			return true;
		}
		else
			return false;
	}
	bool operator>(const Date& d)const
	{
		if ((_year > d._year)
			|| (_year == d._year && _month > d._month)
			|| (_year == d._year && _month == d._month && _day> d._day))
		{
			return true;
		}
		else
			return false;
	}
};
namespace bit
{
	template<class T>
	struct less
	{
		bool operator()( const T& x1, const T& x2)const
		{
			return x1 < x2;
		}
	};
	//特化
	template<>
	struct less<Date*>
	{
		bool operator()( Date* x1, Date* x2)const
		{
			return *x1 < *x2;
		}
	};
}
int main()
{
	bit::less<Date>lessFunc1;
	cout << lessFunc1(d1, d2) << endl;

	bit::less<Date*>lessFunc2;
	cout << lessFunc2(p1, p2) << endl;

	std::priority_queue<Date, vector<Date>, bit::less<Date>>dq1;
	dq1.push(Date(2022, 9, 27));
	dq1.push(Date(2022, 9, 25));
	dq1.push(Date(2022, 9, 28));
	dq1.push(Date(2022, 9, 29));
	while (!dq1.empty())
	{
		Date top = dq1.top();
		cout << top._year << "/" << top._month << "/" << top._day << endl;
		dq1.pop();
	}
	cout << endl;
	std::priority_queue<Date*, vector<Date*>, bit::less<Date*>>dq2;
	dq2.push(new Date(2022, 9, 27));
	dq2.push(new Date(2022, 9, 25));
	dq2.push(new Date(2022, 9, 28));
	dq2.push(new Date(2022, 9, 29));
	while (!dq2.empty())
	{
		Date* top = dq2.top();
		cout << top->_year << "/" << top->_month << "/" << top->_day << endl;
		dq2.pop();
	}
	return 0;
}

PS:(1)特化不能单独存在;

5.3.1 全特化

全特化:将模板参数列表中所有参数都确定化:

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:
	int _d1;
	char _d2;
};
int main()
{
	Data<int, int>d1;   //走模板类
	Data<int, char>d2;  //走全特化类
}

5.3.2 偏特化

偏特化:任何针对模板参数进一步进行条件限制设计的特化版本:

(1)模板参数是普通类型:

template<class T1, class T2>
class Data
{
public:
	Data() { cout << "Data<T1, T2>" << endl; }
private:
	T1 _d1;
	T2 _d2;
};
//偏特化
template<class T1>
class Data<T1,int>
{
public:
	Data() { cout << "Data<T1,int>" << endl; }
private:
	T1 _d1;
	int _d2;
};
int main()
{
	Data<int, int>d1;   //走偏特化类
	Data<int, char>d2;  //走模板类
}

(2)模板类型是指针:

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

template<class T1,class T2>
class Data<T1*,T2*>
{
public:
Data(){cout<<"Data<T1*,T2*>"<<endl;}
private:
T1* _p1;
T1* _p2;
};
int main()
{
Data<double*,double*>d1;    //走指针偏特化
Data<double*,int>d2;       //走模板特化
Data<double*,int*>d3;      //走指针偏特化
return 0;
}

 (3)模板类型是引用:

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

template<T1,T2>
class Data<T1&,T2&>
{
public:
Data(){cout<<"Data<T1&,T2&"<<endl;}
};
int main()
{
Data<int,char>d1;
Data<int&,char&>d2;
return 0;
}

6.模板分离编译

6.1  分离编译模式

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

6.2 模板的分离编译

一般情况下,模板不支持分离编译;

6.3 解决方法

(1)将声明和定义放在同一文件“xxx.hpp”或“xxx.h”中;

(2)模板定义的位置显式实例化(换一次类型则显式实例化一次,不推荐);

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++】_5.模板 的相关文章

  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • C 预处理器库

    我的任务是开发源分析工具C程序 并且我需要在分析本身之前预处理代码 我想知道什么是最好的图书馆 我需要一些重量轻 便于携带的东西 与其推出自己的 为什么不使用cpp这是的一部分gcc suite http gcc gnu org onlin
  • Qt moc 在头文件中实现?

    是否可以告诉 Qt MOC 我想声明该类并在单个文件中实现它 而不是将它们拆分为 h 和 cpp 文件 如果要在 cpp 文件中声明并实现 QObject 子类 则必须手动包含 moc 文件 例如 文件main cpp struct Sub
  • Web API - 访问 DbContext 类中的 HttpContext

    在我的 C Web API 应用程序中 我添加了CreatedDate and CreatedBy所有表中的列 现在 每当在任何表中添加新记录时 我想填充这些列 为此目的我已经覆盖SaveChanges and SaveChangesAsy
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • 如何返回 json 结果并将 unicode 字符转义为 \u1234

    我正在实现一个返回 json 结果的方法 例如 public JsonResult MethodName Guid key var result ApiHelper GetData key Data is stored in db as v
  • C# 中的递归自定义配置

    我正在尝试创建一个遵循以下递归结构的自定义配置部分
  • 在数据库中搜索时忽略空文本框

    此代码能够搜索数据并将其加载到DataGridView基于搜索表单文本框中提供的值 如果我将任何文本框留空 则不会有搜索结果 因为 SQL 查询是用 AND 组合的 如何在搜索 从 SQL 查询或 C 代码 时忽略空文本框 private
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • 将 unsigned char * (uint8_t *) 转换为 const char *

    我有一个带有 uint8 t 参数的函数 uint8 t ihex decode uint8 t in size t len uint8 t out uint8 t i hn ln for i 0 i lt len i 2 hn in i
  • 实体框架 4 DB 优先依赖注入?

    我更喜欢创建自己的数据库 设置索引 唯一约束等 使用 edmx 实体框架设计器 从数据库生成域模型是轻而易举的事 现在我有兴趣使用依赖注入来设置一些存储库 我查看了 StackOverflow 上的一些文章和帖子 似乎重点关注代码优先方法
  • 插入记录后如何从SQL Server获取Identity值

    我在数据库中添加一条记录identity价值 我想在插入后获取身份值 我不想通过存储过程来做到这一点 这是我的代码 SQLString INSERT INTO myTable SQLString Cal1 Cal2 Cal3 Cal4 SQ
  • C++ fmt 库,仅使用格式说明符格式化单个参数

    使用 C fmt 库 并给定一个裸格式说明符 有没有办法使用它来格式化单个参数 example std string str magic format 2f 1 23 current method template
  • 如何让Gtk+窗口背景透明?

    我想让 Gtk 窗口的背景透明 以便只有窗口中的小部件可见 我找到了一些教程 http mikehearn wordpress com 2006 03 26 gtk windows with alpha channels https web
  • 将文本叠加在图像背景上并转换为 PDF

    使用 NET 我想以编程方式创建一个 PDF 它仅包含一个背景图像 其上有两个具有不同字体和位置的标签 我已阅读过有关现有 PDF 库的信息 但不知道 如果适用 哪一个对于如此简单的任务来说最简单 有人愿意指导我吗 P D 我不想使用生成的
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • 为什么我收到“找不到编译动态表达式所需的一种或多种类型。”?

    我有一个已更新的项目 NET 3 5 MVC v2 到 NET 4 0 MVC v3 当我尝试使用或设置时编译出现错误 ViewBag Title财产 找不到编译动态表达式所需的一种或多种类型 您是否缺少对 Microsoft CSharp
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我

随机推荐

  • 基于MATLAB的WSN网络时间同步仿真

    目录 1 算法概述 2 仿真效果 3 matlab仿真源码 1 算法概述 WSN时间同步 时钟偏移与同步问题 主讲教师 马小林 1 时钟偏移与同步问题 1 时钟偏移与同步问题 时钟偏移 时钟之间的时间差 Clock Offset WSN系统
  • 【王道·计算机网络】第一章 计算机网络基本体系

    一 计算机网络概述 1 概念 计算机网络是一个将分散的 具有独立功能的计算机系统 通过通信设备与线路连接起来 由功能完善的软件实现资源共享和信息传递的系统 简而言之 计算机网络就是一些互联的 通过通信链路互联互通 自治的计算机系统的集合 2
  • pycharm:Updating Indices 解决办法

    pycharm Updating Indices 解决办法 右下角一直在update 然后我的文件夹里面文件很多 都是图片流 pycharm相当于预加载这些 然后在左侧可以查看 但是这个过程比较慢 解决的方法是让pycharm直接无视某些文
  • Window下用caffe实现MNIST训练

    本博包含MNIST原始数据的格式转化 以及分类训练 1 数据转化 Caffe源码中src caffe caffe examples mnist convert mnist data cpp提供的实现代码并不能直接在Windows下运行 这里
  • Filebeat监控 日志监控

    介绍 filebeat提供了两种监控 一种直接推送到ES集群 第二种就是Metricbeat 这里介绍第一种 也就四部 第1步 创建认证 账号密码 这一步基本可以略过了 如果你的filebeat在运行 你肯定已经有账号密码了 第2步 配置f
  • 设计模式学习笔记-工厂模式

    设计模式学习笔记 工厂模式 作用 实现了创建者和调用者的分离 详细分类 简单工厂模式 用来生产同一等级结构中的任意产品 对于增加新的产品 必须要扩展已有的代码 工厂方法模式 用来生产同一等级结构中的固定产品 支持增加任意产品 抽象工厂模式
  • 基于Zinx框架实现轻量级TCP服务器

    一 框架部分 包括一个sever 两个读 写模块 一个API管理 一个消息队列管理 一个读写池 建目录一个抽样层 一个实体层 二 基于zinx服务器的应用 对于一个框架 越简单来说越好 V0 1 简单的服务器客户端 1 对于开始 完成简单的
  • 使用CMake构建复杂工程

    转 https www cnblogs com autophyte p 6147751 html 0 什么是CMake CMake是一个跨平台的编译 安装 测试以及打包工具 CMake不直接编译软件 而是结合原生构建系统来构建软件 CMak
  • 计算机视觉之目标检测——R-CNN、Fast R-CNN和Faster R-CNN详解

    计算机视觉之目标检测 R CNN Fast R CNN和Faster R CNN详解 文章目录 计算机视觉之目标检测 R CNN Fast R CNN和Faster R CNN详解 目标检测的任务 目标检测的方法 R CNN Fast R
  • yagmail发送邮件

    分五步实现 1 导入yagmail第三方库 2 连接邮箱 3 添加邮件内容 4 发送邮件 5 释放邮箱 导入yagmail第三方库 import yagmail yagmail SMTP user 邮箱名 host SMTP服务器域名 ya
  • Vue 下拉框值变动事件传多个参数

    在使用 Vue 进行开发时 下拉框值变动事件 change 是很常用的 其传参一般分为两种方式 默认传参和自定义传参 默认传参 change 默认会传选中项标识的参数 在传参处不用定义 在方法中直接接受即可
  • Linux下的ssh

    SSH 为 Secure Shell 的缩写 由 IETF 的网络工作小组 Network Working Group 所制定 SSH 为建立在应用层和传输层基础上的安全协议 SSH 是目前较可靠 专为远程登录会话和其他网络服务提供安全性的
  • 将MindManager添加到鼠标右键新建项

    事情缘起于自己做事习惯为每个项目添加一个思维导图作为项目总看板 但每次都需要自己通过软件新建一个空白文件 再将空白文件索引到项目文件夹 再更名保存 虽然步骤不太多 但每次都需要这样的操作确实让我很困扰 所以就心想能不能让Mindmanage
  • ORM 的功能

    ORM要完成对象的初始化以及CRUD功能 在这些功能中尤其是query和update已经蕴含了相应的map的功能 除此之外还要提供transaction和concurrency的功能 这些基本的功能很好理解 不过相应的实现是比较复杂的 还要
  • 机器学习之朴素贝叶斯

    机器学习之朴素贝叶斯 1 朴素贝叶斯 2 朴素贝叶斯应用 3 代码实现贝努力朴素贝叶斯 4 代码实现高斯朴素贝叶斯 5 代码实现多项式朴素贝叶斯 6 总结 前言 主要介绍朴素贝叶斯的概念 公式 以及代码实现贝努利 高斯 多项式朴素贝叶斯 1
  • PyQt6 Designer与实际运行不一致问题

    我们在Designer设计布局时 会先定义好布局然后只在某个布局内存放元素 其他布局为空 可能就会产生布局不一致问题 其实已经存在了对应的布局只是里面为空 所以剩余空间优先被有元素的布局使用 我们在每个布局中加入某个组件即可解决
  • VC++ CMemDC类的扩展(新版)

    上一版本链接 https blog csdn net u012156872 article details 103755254 测试过程中发现存在问题 于是进行了功能补充 源码实现 CSWMemDC h pragma once namesp
  • vant + moment插件自定义count-down倒计时

    根据vant官网https vant ui github io vant v2 zh CN按需引入找到倒计时 自定义时间格式参考下图
  • matlab2016b版本安装

    安装包下载地址 链接 https pan baidu com s 1RrUp8TBIa7g7mhfSUtqAsg 提取码 foc1 1 解压文件包 2 在 matlab R2016b 64bit 文件下 找到 setup 文件 右击选择 以
  • 【C++】_5.模板

    目录 1 泛型编程 2 函数模板 2 1 概念 2 2 函数模板格式 2 3 函数模板原理 2 4 函数模板的实例化 2 5 函数模板的匹配原则 3 类模板 4 非类型模板参数 5 模板的特化 5 1 概念 5 2 函数模板特化 5 3 类