c++的类模板

来源:互联网 发布:剑网三捏脸数据免费 编辑:程序博客网 时间:2024/06/05 11:58

1. 类模板

  泛型思想可运用于函数即函数模板外,还可以运用于类即模板类,使得类的实现不关注数据元素的具体类型,而只关注类所需要实现的功能。模板类在实际中主要用于存储和组织数据元素,如数组类、链表类、栈类(后进先出)、队列类(先进先出)等,这些类的共同之处为:类中的数据组织方式和数据元素的具体类型无关。

  模板类的语法如下:

template<typename T>class TestCls{public:    T func(T a, T b)    {        //...    }};

  模板类的意义跟模板函数意义一样,在于以相同的方式处理不同的数据类型。与模板函数不同的是,模板类的使用只能显示指定具体类型,无法自动推导,需要使用具体类型“<类型>”定义对象:

TestCls<double> t1;TestCls<std::string> t2;double i = t1.func(4, 5);std::string ss = t2.func("HelloWorld\n");

  编译器对模板类的处理方式和模板函数相同:
  a. 同是通过对函数模板的具体类型的调用产生不同的类;
  b. 同是进行两次编译:在声明的地方对类模板代码本身进行编译,在使用的地方对参数类型替换后的代码再次进行编译。

  在实际工程中,类模板是在头文件中定义,且类模板中的函数的实现不能分开实现在不同的文件中,类模板外部定义的成员函数需要加上<>声明。

  来个简单的例子:

//13_class_template.h#ifndef __CLASS_TEMPLATE_H__#define __CLASS_TEMPLATE_H__template <typename T>class calculate {public:    T add(T a, T b);    T subtract(T a, T b);    T multiplication(T a, T b);    T divide(T a, T b);};template <typename T>T calculate<T>::add(T a, T b){    return a + b;}template <typename T>T calculate<T>::subtract(T a, T b){    return a - b;}template <typename T>T calculate<T>::multiplication(T a, T b){    return a * b;}template <typename T>T calculate<T>::divide(T a, T b){    return a / b;}#endif /* __CLASS_TEMPLATE_H__ */
//13_class_template.cpp#include <stdio.h>#include "13_class_template.h"int main(void){    calculate<int> op;    printf("op.add(1, 2) = %d\n", op.add(1, 2));    printf("op.subtract(5, 2) = %d\n", op.subtract(5, 2));    printf("op.multiplication(12, 2) = %d\n", op.multiplication(12, 2));    printf("op.divide(8, 2) = %d\n", op.divide(8, 2));    return 0;}

  编译运行:
这里写图片描述

  注意,calculate类的实现还是存在缺陷,如string类型的减法操作:

std::cout << "op.subtract(\"hello\", \"world\") = " << op.subtract("hello", "world") << std::endl;

  对std::string类型的两个变量进行减法运算,编译器显然没有这种实现:
这里写图片描述

  用操作符重载减号操作符的方式加以区分实现:

std::string operator- (std::string a, std::string b){    return "Error";}

  这样当T数据类型为std::string时,op.subtract(“hello”, “world”)的实现体为:

std::string s = "hello" - "world" ;

  编译器就会根据上下文调用operator- (std::string a, std::string b):
这里写图片描述

2. 类模板的本质

  (1) 和函数模板一样,类模板也可以定义任意多个不同的类型参数,如:

template <typename T1, typename T2>class TestCls{public:    void add(T1 a, T2 b);};template <typename T1, typename T2>void TestCls <T1, T2>::add(T1 a, T2 b){    printf("estCls <T1, T2>::add(T1 a, T2 b) = %d\n", a + b);}

  (2) 类模板也支持特化,以满足在某种特定类型下的类模板需要特定实现的需求,如:

//部分特化template <typename T>class TestCls <T, T>{public:    void add(T a, T b);};template <typename T>void  TestCls <T, T>::add(T a, T b){    printf("TestCls <T, T>::add(T a, T b) = %d\n", a + b);}

  这种称为部分特化:只用特定的规则约束类型参数,特化后的数据类型还是泛指类型T。在这里,原先是T1、T2类型,二者既可以是同一种类型,也可以是不同一种,特化后T1、T2只能是相同的一种类型T。当我们定义的对象的T1、T2类型是一样的时候,编译器会选择特化后的类模板:

int main(void){    TestCls<int, int> t;    //编译器会选择特化后的类。                            //注意<>内不能为空,编译器对类模板不能进行类型推导。    t.add(5, 5);    return 0;}

  编译运行:
这里写图片描述

  类模板还支持完全特化,即类模板的类型参数完全指定,如:

//完全特化,完全特化后"<>"内为空template <>class TestCls<int, char>        //直接指定T1、T2的类型{public:    void add(int a, char b)    {        printf("TestCls<int, char>::add(int a, char b)\n");    }};int main(void){    TestCls<int, char> t;    t.add(5, 5);    return 0;}

  编译运行:
这里写图片描述

  注意,特化只是模板的分开实现,本质上还是同一个类模板,特化类模板在使用方式是与类模板是一样的,即必须显式的指定每一个类型参数(编译器不会自动推导)。

  (3) 重新定义类还是完全特化类模板
重新定义一个类和完全特化类模板都可以实现在某种特定类型下实现某种特定的操作,但是重新定义类后就需要考虑调用哪一个类的问题:

//类模板template <typename T1, typename T2>class TestCls{public:    void add(T1 a, T2 b);};//部分特化template <typename T>class TestCls <T, T>{public:    void add(T a, T b)    {        printf("TestCls <T, T>::add(T a, T b) = %d\n", a + b);    }};//完全特化template <>class TestCls<int*, int*>       //直接指定T1、T2的类型{public:    void add(int *a, int *b)    {        printf("TestCls<int*, int*>::add(int *a, char *b) = %d\n", *a + *b);    }};//重新定义类class TestCls_INT{public:    void add(int* a, int* b)    {        printf("TestCls_INT::add(int* a, int* b) = %d\n", *a + *b);    }};int main(void){    int a = 8, b = 3;    TestCls_INT t1;         //重新定义类需要考虑调用的是哪一个类    t1.add(&a, &b);    TestCls<int*, int*> t2;    t2.add(&a, &b);    TestCls<int, int> t3;    t3.add(a, b);}

编译运行:
这里写图片描述

  在前面讲到的函数模板,它也支持特化,但是注意,函数模板只支持完全特化,特化后的函数模板没有出现泛指数据类型,也就是template的语句为”template <>”。有关内容在记录在文章http://blog.csdn.net/qq_29344757/article/details/77394049中。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孕婴店装修效果图 小户型厨房装修效果图 联排别墅装修效果图 80平方的房子装修图 90平方房屋设计图 小平米装修效果图 新房子装修效果图 室内简单装修效果图大全 儿童卧室装修效果图小户型 小户型装修效果图大全2015图片 楼中楼装修效果图小户型 三室两厅装修效果图现代简约 现代装修风格效果图客厅 简约客厅装修实景图大全 90平方米简约装修效果图 190平方房子装修效果图 8平米卫生间装修效果图 100平方房屋装修效果图 四室两厅两卫装修效果图 130平米三室两厅装修效果图 八十平米小户型设计效果图 三室一厅一厨一卫装修效果图 七十平米小户型装修效果图 200平方米的房子设计图 75平方两室一厅装修效果图 113平方三室两厅装修效果图2015 85平米两室一厅装修效果图 四十平米小户型装修效果图 三房两厅两卫装修效果图 现代简约客厅装修效果图 3平方米卫生间装修效果图 主人房卫生间装修效果图 110平米三室两厅装修效果图 30平米单身公寓装修效果图 现代简约风格装修效果图 65平米小户型装修效果图大全 家装评选 装修帮登陆 家装帮 东易日盛全屋定制家装 东易日盛家装怎么样