c++模板入门笔记

本文深入讲解了C++中的模板概念,包括STL的使用方法、函数模板和类模板的定义及调用方式,探讨了模板参数、重载、静态成员初始化、默认模板参数等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c++模板包含c++自带的stl,函数模板和类模板

1.stl

stl是标准模板库,比如list,vector,map等,使用方法就不说了,这里说下添加数据问题

假如添加内容为结构体TData,使用的是list,添加方法如下:

方法1:直接添加结构体

typedef list<TData>  DATALIST;

DATALIST datalist ;

TData tData;

datalist .push_back(tData);

说明:stl里的push_back里会自动new一份,且如果传入的是类对象,在stl容量不足时,会自动扩容,并调用该类的拷贝构造函数,如果没有,则调用默认的拷贝构造函数(如A(&A)),默认拷贝构造函数只会拷贝值,不会分配内存

有兴趣的请自行搜索stl中push_back和浅拷贝和深拷贝的问题,原因终归是类写的有问题,解决办法是写类的时候,涉及到内存的记得加上拷贝构造函数,毕竟这类情况一旦出现很难定位


方法2:添加指针

typedef list<TData*>  DATALIST;

DATALIST datalist  ;

TData *ptData = new  TData;

datalist .push_back(ptData );

错误使用情况:

TData tData;

datalist .push_back(&tData);


如果不使用new的情况,调试会发现里面所有数据都是相同的即第一个值的内容,原因暂不清楚,如果使用new内容才会正常


说明:

(1)stl使用时后面的<>里的跟的是数据类型,不要定义变量即<TData tData>

(2)方法2较方法1而言,在数据交互比较频繁的情况下会占用太多内存,而且要防止使用的上面的那种错误情况,方法1则不存在这些问题


2.函数模板

(1)格式:

template<class T> 

void fun(T t)

{

}

或者

template<class T>  void fun(T t)
{

}

两者是一样的,且template<class T> 和函数两者必须在一起,中间不能含有其他东西,如

template<class T> 

int a = 0;

void fun(T t)

{

}

说明:c++中的函数模板,声明和定义要一起放在头文件中,因为函数模板并不是真正的函数,只有在使用的时候才会被实例化,如果一个放在.h中,一个放在.cpp中,不使用时编译不会报错,但是一旦使用,编译时就会提示“未定义的函数”错误

正确例子:

fun.h文件:
#ifndef _FUN_H_
#define _FUN_H_

template<class T> bool MAX_SIZE(T a, T b)
{
	return a>b ? true:false;
}

#endif

(2)调用方式:隐式调用和显示调用

隐式调用:MAX_SIZE(2,3)

显示调用:MAX_SIZE<int>(2,3),其<>中的内容和数量要保持与templat<>中的一致


(3)函数模板支持重载,非模板参数,不支持默认模板参数

1>重载

template<class T> bool MAX_SIZE(T a, T b)
{
return a>b ? true:false;
}

bool MAX_SIZE(int a, char b)

{

       return a>(int)b ? true:false;

}

说明:

函数模板内部不支持类型自动转化,无法处理传入参数不同的情况,可以通过重载的方式解决

2>非模板参数

template<class T, int nValue> bool MAX_SIZE(T a)
{
return a>nValue ? true:false;
}

使用:MAX_SIZE<int, 2>(3);

非模板参数类型只能显示调用

3>不支持默认模板参数

template<class T=int, int b> bool MAX_SIZE(T a)
{
return a>b ? true:false;
}

template<class T, int b=2> bool MAX_SIZE(T a)
{
return a>b ? true:false;
}

template<class T=int, int b=2> bool MAX_SIZE(T a)
{
return a>b ? true:false;
}

编译直接报错“仅允许在类模板上使用默认模板参数


3.类模板

(1)格式:

template<class T>

class test
{
public:
test();
~test();
};

或者

template<class T> class test

{
public:
test();
~test();
};

说明:同函数模板一样,c++中的类模板,声明和定义要一起放在头文件中,因为类模板并不是真正的类,只有在使用的时候才会被实例化,如果一个放在.h中,一个放在.cpp中,不使用时编译不会报错,但是一旦使用,编译时就会提示“未定义的...”错误


正确例子:

classtest.h
#ifndef _TEM_H_
#define _TEM_H_

template<class T> class test
{
public:
	test();
	~test();

	void show(T t);
private:
	T m_t;
};

template<class T> test<T>::test()
{

}

template<class T> test<T>::~test()
{

}

template<class T> void test<T>::show( T t )
{
	cout << t <<endl;
}

#endif//_TEM_H_
这里将声明和定义分开了,实际上大多数时候直接将实现内容放在类里,因为放在外面书写真的很麻烦


调用:

test<int> ctest;
ctest.show(2);


(2)类模板初始化静态成员

例子:

classtest.h
#ifndef _TEM_H_
#define _TEM_H_

template<class T> class test
{
public:
	test();
	~test();

	static void showst()
        {
           cout << m_st <<endl;
         };
private:
	static T m_st;
};

#endif//_TEM_H_


如果你希望所有实例化的类静态值都一样,在上面类的大括号“}”下面加上:

template<class T> T test<T>::m_st = 0;

使用:

#include "stdafx.h"
#include "iostream"
#include "classtest.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
	test<int> ctest;
	ctest.showst();

	system("pause");
	return 0;
}


如果你希望每个实例化的类静态值不一样,那么声明的地方不要初始化,可以在使用这个类模板的cpp中初始化即可(只要在使用对应函数前初始化就行),如

#include "stdafx.h"
#include "iostream"
#include "classtest.h"
using namespace std;

template<> int test<int>::m_st = 1;
template<> long test<long>::m_st = 2;

int _tmain(int argc, _TCHAR* argv[])
{
	test<int> ctest;
	ctest.showst();

        test<long> ltest;
	ltest.showst();

	system("pause");
	return 0;
}

(3)c++类模板支持默认模板参数、inl文件

1>默认模板参数

template<class T=int,int nValue> class test

{

}

template<class T,int nValue=4> class test
{
}


template<class T=int,int nValue=4> class test
{
}

使用时用test<> ctest创建对象即可,上面第三个可以这样用,其他两个不全是默认参数,不能这样用


具体例子:

classtest.h
#ifndef _TEM_H_
#define _TEM_H_

template<class T=int> class test
{
public:
	test();
	~test();

	void show(T t);
private:
	T m_t;
};

template<class T> test<T>::test()
{

}

template<class T> test<T>::~test()
{

}

template<class T> void test<T>::show( T t )
{
	cout << t <<endl;
}

#endif//_TEM_H_

使用:

#include "stdafx.h"
#include "iostream"
#include "classtest.h"
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	test<> dtest;
	dtest.show(3);

	system("pause");
	return 0;
}

2>inl文件

inl文件是内联函数源文件(存放内联函数的文件),在类模板里,如果实现过于复杂,可以将所有实现都放在inl文件里,在.h文件里用#include包含inl文件即可

classtest.h
#ifndef _TEM_H_
#define _TEM_H_

template<class T> class test
{
public:
	test();
	~test();

	void show(T t);
	static void showst();
private:
	T m_t;
	static T m_st;
};


#include "classtest.inl"

#endif//_TEM_H_

新建记事本txt文件,把实现内容都拷到txt里,另存为inl文件即可,inl文件头记得加#ifndef...,防止重复

classtest.inl
#ifndef _TEM_INL_
#define _TEM_INL_

template<class T> test<T>::test()
{

}

template<class T> test<T>::~test()
{

}

template<class T> void test<T>::show( T t )
{
	cout << t <<endl;
}

template<class T> void test<T>::showst()
{
	cout << m_st <<endl;
}

#endif//_TEM_INL_

(4)类模板里包含函数模板

classtest.h
#ifndef _TEM_H_
#define _TEM_H_

template<class T> class test
{
public:
	test();
	~test();

	template<class V> void fun(V v)
	{
		cout << "v:" << v <<endl;
	}
};

#endif//_TEM_H_


使用:
#include "stdafx.h"
#include "iostream"
#include "classtest.h"

using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
	
	test<int> dtest;
	dtest.fun<int>(5);

	system("pause");
	return 0;
}

类模板支持默认参数,类模板中函数模板同样不支持默认参数

(5)类模板的声明

c++中一个普通的类如class A,声明时直接在使用的头文件中加class A即可,如果是类模板实例化后,则对应的声明是在前面加一个template即可

如:template class test<int>;//类声明的格式,不是template<> class test<int>,容易犯错误的就是这里









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kevin--你不知道的事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值