c++ 模板问题,请高手给讲一下

作者&投稿:比性 (若有异议请与网页底部的电邮联系)
  1. 首先,模板函数f<double>(-1.00),根据-1.00可以推导出t2类型为double,但是不能推导返回值的类型,所以需要在调用函数是指定即f<double>,这里的double是t1的类型。所以当你将t1,t2互换了后:

    template <typename t2,typename t1>
    t1 f(t2 const & x)
    {
    return x;
    }

        f<double>的意思是指定t2的类型为double,t2的类型其实不用指定,它可以从-0.01参数推导出来,反而是返回类型t1,函数无法自动推导,所以编译通不过。

2. 输出-1很正常,如果你调用f(-1.01),它就会输出-1.01,因为cout会自动处理输出格式的。如果你要保留几位小数,需要设置cout的输出格式。



#include <iostream>    
#include <iomanip>//添加这个头文件
using namespace std;

template <typename t2,typename t1>
t1 f(t2 const & x)
{
return x;
}

int main()
{

double v=f<double, double>(-1.00);//你这里也写错了,这也是你“调换类模板的声明交换t1 、t2时就会出现错误”的原因
cout<<setiosflags(ios::fixed)<<setprecision(2)<<v<<endl;//设置精度

system("pause");
return 0;
}


这是因为使用的时候f<double>(-1.00);只指定了一个类型,如果f<double,double>(-1.00);就可以了

应该是输出精度的问题,添加头文件<iomanip>
然后输出地方改成
cout<<setiosflags(ios::fixed)<<setprecision(2)<<v<<endl;

第二个问题如果有一个函数模板,它的模板参数即作为参数类型又作为返回类型那么一定要首先申明函数的返回参数类型,否则就不能神略掉函数参数表中的任何类型参数。具体看这里吧http://blog.csdn.net/lgp88/article/details/7054973

c++的模板对c的什么?~

C++模板在C中没有对应的东西。
可以参考STL标准摸板库的资料

参考读物:
《Thinking in C++: vol1 & vol2》 Bruce Eckel - www.bruceeckel.com
《C++ Template》 David Vandevoorde, Nicolai M. Josuttis

推荐读物:
《modern C++ design》Andrei Alexandrescu

1 介绍
模板是一个包含有未指定类型的函数或类,因此模板并不是一个真正的函数或类,而是代表了一组函数或类,当为模板函数或类指定了一种类型时,就生成了此模板的一个实例,这个操作叫做模板实例化(instantiation)。也可以为某一种类型提供不同于模板的定义,这个称为特化定义(specialization)。对于有多个类型参数的模板,还可以只指定一部分类型,这个称为偏特化定义(partial specialization)。
模板不是实体,因此模板的声明和定义通常都放在头文件中。

2 函数模板
2.1 声明
template
inline void func(T param)
{
}

2.2 函数模板不支持默认类型参数,但支持函数的默认参数
template
void func(T param, int size = sizeof(T))
{
}

2.3 函数模板显式实例化声明
template void func(int param);
显式实例化后的函数模板不能再有不能转换的类型的调用
显式实例化后的函数模板不能被特化定义

2.4 特化定义函数模板
template
void func(int param) //函数模板只支持全特化
{
}
特化后是一个实体函数,不再是模板,放在头文件中会导致重定义

2.5 函数模板重载
template
void func(T param, int i)
{
}
template
void func(ClassName param, int i)
{
}
void func(int i)
{
}
这几种func函数的定义,匹配的顺序是非模板函数 -> 特化函数模板 -> 基函数模板。如果不像func(100)这样指定函数模板的参数类型的话,编译器会为函数模板推测出一种类型,如根据100为int类型,编译器会自动调用func,称为隐式特化,而前者则成为显式特化。

为什么函数模板要特化呢?这是因为有时候函数模板并不能处理所有情况,对于个别情况就可以使用特化来替换掉原来模板。

3 类模板
3.1 声明
template
class ClassName
{
};

3.2 类方法类外定义
template
ReturnType ClassName::Func()
{
};

3.3 非类型(nontype)模板参数
如template class bitset {}就是使用size_t类型参数设置位的个数。
可以是常量整数类型(包括枚举)或外部链接(external linkage)对象的指针或引用作为模板参数,不能是浮点型和类对象。
char *s = "hello"; //s不可以,直接使用"hello"亦不可以,因为两个"hello"可能为不同地址
char s[] = "hello"; //s可以
ClassName obj; //obj可以
ClassName obj; //obj可以
什么是一个外部链接对象呢?
关于这个问题,专门转载了SpitFire同志的一篇文章《内部链接和外部链接》到博客中

总的说来,要作为参数必须满足:1、在编译时和链接时可以求值; 2、这个参数如果是指针,则它所指的变量,如果在两个cpp中定义会出链接错误。

不同的参数值构成不同的类型,bitset和bitset是两个类型

3.4 默认参数
template
class ClassName
{
};

3.5 以模板为类型参数的类模板声明
template
class Array;
template class T2>
class ClassName
{
T2 m_o;
}

如果T2是带默认参数的:template class T2; 则在以它为类型参数的类中必须再次指明默认值,如果两个默认值不同以再次声明的为准。
template
class Array;
template class T2>
class ClassName
{
T2 m_u;
}
使用:
ClassName obj;


3.6 特化模板类
template
class ClassName
{
};

3.6.1 全特化
template
class ClassName
{
}; //特化后是一个实体类,不再是模板

3.6.2 偏特化
template
class ClassName
{
}; //特化后是一个实体类,仍是模板

template
class ClassName
{
};

3.6.3 类成员函数特化
template
class ClassName
{
public: void f();
};
template
inline void class ClassName :: f()
{
} //特化类ClassName的f(),T为int类型时优先调用此定义

3.7 模板类里的静态变量
template
class ClassName
{
static T a;
}

定义:
int ClassName::a = 100; /* 定义一个与类模板的类型参数对应的静态变量 */
main()
{
ClassName o;
}

3.8 typename关键词

3.8.1 表明紧跟在后面的是类型,而不是其他(如静态变量)
typename vector::iterator it;

3.8.2 定义新类型
typedef typename vetor::iterator Iterator_Type;

3.8.3 代替模板中的class关键词
template
class ClassName
{
};

3.9 模板类中的成员函数模板
template
class ClassName
{
public:
template T m_func(T1 a, T2 b);
}

类外定义:
template
template
T ClassName::m_func(T1 a, T2 b)
{
}

特化
template
template
int ClassName::m_func(int a, int b) //类必须被一起全特化
{
}

调用:
ClassName o;
o.template m_func >(100, vector()); //调用时实例化


3.10 继承模板类
template
class Chlid : public Parent
{
};

3.10.1 特化继承
class ClassName : public vector
{
};

3.11 explicit关键字
explicit Y(const X& x);
X x; Y y(x); //显式转换
X x; Y y = x; //隐式转换,编译不通过

第一条语句通过使用显式从X类型转换生成了一个Y类型的对象,后一条语句则使用了隐式转换创建。由于使用了explicit要求必须使用显式,所以编译没有通过。

4 总结
模板加强了使用C++编写可复用代码的能力,但是想学好模板需要花费很大的功夫和精力的,而最难的就是将模板和原有C++面向对象的技术,如继承和多态等,相互融会贯通。