码迷,mamicode.com
首页 > 其他好文 > 详细

类模板 及其 特化

时间:2019-03-04 22:30:48      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:double   oid   int   equal   部分   typename   否则   ast   span   

(1)

// -------------类模板 体验--------------------
template <typename T1, typename T2>
class Test //原始的类模板后 加上class Test<T1, T2>会报错
{
public:
void add(T1 a, T1 b)
{
cout << "void add(T1 a, T1 b)" << endl;
cout << "a + b = " << a+b << endl;
}
};

template <typename T1, typename T2>
class Test<T1*, T2*> // class Test<T1, T2>报错 。但是class Test<T1*, T2*>不会报错
{
public:
void add(T1* a, T2* b)
{
cout << "void add(T1*a, T2* b)" << endl;
cout << "*a + *b = " << *a + *b << endl;
}
};


//template <typename T, typename T_again> 这是不被编译器允许的。泛指类型T_again没有被使用,会引起编译报错。
template <typename T>
class Test<T, T>
{
public:
void add(T a, T b)
{
cout << "void add(T a, T b) "<< endl;
cout << "a + b = " << a+b << endl;
}
};
/* 这个模板类和上面的这个本质是同一个模板类。
template <typename T2>
class Test<T2, T2>
{
public:
void add(T2 a, T2 b)
{
cout << "void add(T a, T b) "<< endl;
cout << "a + b = " << a+b << endl;
}
};
*/


template < > // 没有泛指类型,是完全特化
class Test < void*, void* > // 当 T1 == void* 并且 T2 == void* 时
{
public:
void add(void* a, void* b)
{
cout << "void add(void* a, void* b)" << endl;
cout << "Error to add void* param..." << endl;
}
};

class myClass{
}; // 编译器默认提供的构造函数是公有的。

int main(void)
{
int x = 12;
unsigned int y = 13;

Test<int ,int> a;
a.add(3, 6);

Test<int*, unsigned int*> b;
b.add(&x, &y);

Test < void*, void* > c;
c.add((void*)&x, (void*)&y);

myClass mytest;

return 0;
}

 

(2)
//-------  模板类的特化 ------------------------------------- 

template
<typename T1, typename T2, typename T3>
class Test{
public:
T3 get_add(T1 a, T2 b)
{
T3 tmp = a+b;
cout<< "原始的 类模板 Test: get_add = "<< tmp << endl;

return tmp;
}
};


template
<typename T1, typename T2>
//class Test<T1, T2>{ // ????? 编译报错 原因: 既然命名为Test,
// 那么编译器肯定认为这是上面那个类的特化实现,所以报错 缺少参数(上面那个类是三个参数的哦)
class Test2{ // 把这里改为Test2以后,编译器认为这个类和上面的Test类没有关系了,这是一个新的类模板,自然也不会报错缺少参数之类的了。
public:
void get_add(T1 a, T2 b)
{
cout<< "这是重新定义了一个新的类模板哦!不是特化!" endl;
}
};


template
<typename T1, typename T2>
class Test<T1, T2, int>{ //由于只指定了一部分参数,剩下的未指定的需在参数列表中,否则编译会报错。
//class Test2{
public:
int get_add(T1 a, T2 b)
{
int tmp = a + b;
cout<< "部分特化的类模板 Test: get_add = "<< a+b << endl;
return tmp;
}
};

 

template<>
//class Test<void*, void*, int>{ // ******* 喜发现,如果这里是void*,那么下面传入int*,即定义Test<int*,int*,int> obj_3;,并不能顺利匹配,会引起编译报错。
class Test<int*, int*, int>{
public:
int get_add(int* p1, int*p2) // main函数内调用该类对象的该成员函数进行二次编译的时候,
{ // 报错 class Test<T1, T2, int>的该部分特化的类模板的成员函数不能进行两个指针的相加。
int tmp = static_cast<int>( *(int*)p1 + *(int*)p2 ); // 所以我在想,难道同一个类模板的部分特化的优先级高于完全特化? 实测NO
cout<< "完全特化的类模板 " ; // 编译器按照部分特化的类的规则,去对我写的完全特化的类,进行编译检查了
// 如果这里是void* 去匹配传入int*, 是有问题的。因为这俩不是同一个类型啊!  所以说,特化遵循严格的类型匹配!
return tmp; // 我们平常习惯了默认提供的的隐式类型转换,这是个毛病。void*和int*不是同一个类型。
}
};


template<>
class Test<int, int, int>{
public:
int get_add(int a, int b)
{
int tmp = a + b;
cout<< "3个int的 完全特化的类模板 Test: get_add = "<< a+b << endl;
return tmp;
}
};

int main()
{
// 范型之--- 类模板 部分特化 完全特化 实验

// int 同类型相加
Test<int, int, int> obj;
int result = obj.get_add(2, 3);
cout << "result = "<< result << endl<< endl;

// float 同类型相加
Test<float, float, float> obj_1;
float result_1 = obj_1.get_add(2.333, 3.3);
cout << "result_1 = "<< result_1 << endl<< endl;

// int float 混合类型相加
Test<int, float, float> obj_2;
float result_2 = obj_2.get_add(2.333, 3.4);
cout << "result_2 = "<< result_2 << endl<< endl;

// 指针类型相加
Test<int*,int*,int> obj_3;

int x1=22; int x2 = 33;
int result_3 = obj_3.get_add(&x1, &x2);

cout << "result_3 = "<< result_3 << endl;

return 0;
}
// 类名很重要,是不是同一个类模板,要看是不是同一个类名。
// 类模板有特化,同一个类模板的类之间,类名肯定都是一样的。
// 类模板的成员函数的实参到形参的传递,int*到void*需要手动去显式转换才ok。 实测是如此。
// int 和 double之类的隐式转换也是类似的。
// 一般的我们认为void*兼容int*之类的。
// 可是在类模板的这个实验里,体现出了的确存在类型不同的问题。
// 用习惯了编译器平时的隐式转换咯!是个毛病。

 

(3)

// --------------------------函数模板 : 函数模板只有完全特化----------------------------------
template < typename T >
bool Equal(T a, T b)
{
cout << "bool Equal(T a, T b)" << endl;

return a == b;
}

// 上述函数模板的一种特化实现
template <>
bool Equal(int a, int b)
{
cout << "bool Equal(int a, int b)"<< endl;
return a == b;
}

/* 突发奇想? 想写个函数模板的部分特化?哈哈,想一想,在main函数内该如何定义生成使用这部分特化的函数模板呢?
template <typename T, char b>
bool Equal(int a, int b)
{
cout << "函数模板部分特化"<< endl; // 函数模板的特化,只有完全特化!
return a == b;
}
*/

int main()
{
cout << Equal( 1, 1 ) << endl;
cout << Equal( 0.001, 0.001 ) << endl;

return 0;
}

 

类模板 及其 特化

标签:double   oid   int   equal   部分   typename   否则   ast   span   

原文地址:https://www.cnblogs.com/happybirthdaytoyou/p/10473688.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!