Skip to main content
 首页 » 资源教程

C++进阶教程之模板2--简单模板类( 附视频)

2016年10月14日 20:47:4010000

中国AR网(微信公众号:armeiti)

1.一个简单的模板类示例


#include <iostream>
#include <string>
template<typename T>
class Array
{
public:
T& operator[](int idx)
{
return m_buf[idx];
}
private:
T m_buf[100];
};


int main()
{
Array<int> test_i;
Array<std::string> test_s;
test_i[0] = 5;
test_s[0] = "aaa";
std::cout << "test_i[0]=" << test_i[0] << std::endl;
std::cout << "test_s[0]=" << test_s[0] << std::endl;
system("pause");
return 0;
}
我在这里简单的写了个用于封装一个可以兼容任何类型的数组的类Array。他只有一个对方括号进行重载的函数,就是想普通的数组一样,可以通过方括号对内部数组的每一个成员进行访问。
下面我们来分析一下这个模板。
他的格式貌似很简单,前面说的模板函数好像也没什么区别~
也就是
template<typename 类型1...,typename 类型n>
class 类名称
{
类内容...
....
} ;
然后其实和模板函数也差不多,我们代码在最上面声明一个模板参数T,则在类内就可以使用这个模板参数了。
就这样,一个最简单的模板类基本就完成了。
2.类模板的特化
我们在给我们的Array模板增加一个函数,assign。代码如下
template<typename T>
class Array
{
public:
T& operator[](int idx)
{
return m_buf[idx];
}
void assign(T value)
{
for (int i = 0; i < size; ++i)
{
m_buf[i] = value;
}
}
private:
T m_buf[100];
};


其中assign就是将array类封装的buf值全部改为value值。
这个函数本来没什么问题,但是我们知道,大批量变量赋值为同一个值,效率最高的是使用memset,但是memset函数是按照字节进行赋值的,也就意味着,需要如果T的类型为bool型或者char型的话,我们assign函数就可以使用memset来实现。
这个需求在其实就叫做特化,意思是对模板的特殊参数进行特殊处理的意思。
下面我们就简单的实现一下。
template<typename T>
class Array
{
public:
T& operator[](int idx)
{
return m_buf[idx];
}
void assign(T value)
{
for (int i = 0; i < size; ++i)
{
m_buf[i] = value;
}
}
private:
T m_buf[100];
};


template<>
class Array<char>
{
public:
char& operator[](char idx)
{
return m_buf[idx];
}
void assign(char value)
{
memset(m_buf, value, 100);
}
private:
char m_buf[100];
};


然后我们就可以看下模板特化的语法是如何的
template<>
class 模板类名称<特化的模板参数值>
{
...
}
也是非常简单的。
3.非类型模板参数
看我开始写的示例代码中,是不是感觉,虽然封装了一个数组,但是数组的大小没办法修改呢???
能不能用模板来传入数组大小的参数呢?
下面我们看看这一段代码
template<typename T, int size>
class Array
{
public:
T& operator[](int idx)
{
return m_buf[idx];
}
private:
T m_buf[size];
};


这里面的模板参数中增加了一个int size,但是和以前的模板参数不同,以前我们接触的模板参数都是个类型,但是这次我们的模板参数竟然和函数参数一样,是个int size。
对我们的参数其实并不是只能是类型,也可以是变量的,当然,函数模板也可以在模板中传入变量,但是由于函数参数中也能传入变量,所以通常我们不会在函数模板中传入变量,只会在类模板中传入变量。
不过这里必须要说一下,模板参数只能传入整数类型的变量,这个整数类型的含义其实有点大,包括bool,char,int。而像什么类类型的,结构体类型的,浮点类型的变量是不能通过函数模板进行传递的。
4.偏特化(局部特化)
template<typename T1, typename T2>
class TestClass
{
...
};


template<typename T>
class TestClass<T, int>
{
...
};


template<typename T>
class TestClass<T, T>
{
...
};


template<typename T1, typename T2>
class TestClass<T1*, T2*>
{
...
};
偏特化和特化的格式其实是很像的,但是呢,他的模板参数只是确定了部分,比如说我们代码中的偏特化分别只是确定了
第二个参数为int型
两个参数类型相同
两个参数都是指针型。
其实常用的偏特化,也就这几种。
然后我们判断几种使用方式分别使用的是哪个类。
TestClass<float, bool> value;\\匹配的是TestClass<T1,T2>
TestClass<float, int> value;\\匹配的是TestClass<T,int>
TestClass<float, float> value;\\匹配的是TestClass<T,T>
TestClass<float*, float*> value;\\匹配的是TestClass<T1*,T2*>
但是这里我就会想个问题。

TestClass<int, int> value;
这种,会匹配那种呢????
是TestClass<T,int>还是TestClass<T,T>呢????
好像都有点像,这里其实是明显的有二义性的,因此,这种使用编译器是会报错的。
5.缺省模板参数
我们都知道普通的函数是有缺省参数这样的说法的
void func(int value = 0)
{
...
}
这个函数,当我们使用func(1)这样调用的时候,value传入的值将为1.但是当我们使用func()这种方式调用时,value的参数将会默认为0.这就是函数的缺省参数。
当我们传入参数时,就是用我们的参数,当我们不传入参数时,就是用缺省参数。既然函数参数有这种特性,那么模板参数有这种特性么?
既然说到这了,肯定是有的~
template<typename T1, typename T2=bool>
class TestClass
{
...
};
当我们使用TestClass<char>的时候,匹配的是TestClass<char, bool>。
然后又想我们上一个教程里面的函数模板中,没说有缺省模板参数啊?其实这是通用的,函数也是可以使用缺省模板参数这个特性的。



另:视频教程:http://v.youku.com/v_show/id_XMTYyMjY0MDI0MA==.html?f=27489531

更多AR教程就在中国AR网(http://www.chinaar.com/)


评论列表暂无评论
发表评论