c语言template的参数是什么,C++的template模板中class与typename关键字的区别分析

在C++模板中,可以使用class或者typename来声明模板参数,那么这两个关键字有什么区别呢?

模板参数声明对于模板参数声明,这两个参数没有区别,含义是一样的。

template class Simple;

template class Simple;

上面两行都是声明一个模板类Simple.

表明类型假如我们有这样一段代码:

template

void add(const T &acontainer, T &sum)

{

T::const_iterator iter = container.begin();

for (; iter != container.end(); ++iter) {

sum += *iter;

}

}

iter的类型是T::const_iterator,这个类型依赖模板参数T。把依赖模板参数的名称称为依赖名称。当这个依赖名称又在一个类中时,称为嵌套依赖名称。相对的,称为非嵌套依赖名称。

嵌套依赖名称会导致编译器编译的困难,例如下面的代码:

template

void add(const T &container)

{

T::const_iterator *x;

...

}

这看起来像声明一个变量x,它的类型为T::const_iterator *。但是编译器并不知道,也有可能类T中又一个static数据成员const_iterator,或者正好有一个全局变量x。这时上面的代码就变成乘法操作。这是因为 C++编译器在处理模板的时候,会将需要推导的数据类型暂时搁置,到运行时再确定。

当编译器遇到一个模板中的嵌套依赖名称时,编译器将它作为变量对待。因此,需要显示的告诉编译器,这就需要使用关键字typename。

template

void add(const T &container, T &sum)

{

typename T::const_iterator iter = container.begin();

for (; iter != container.end(); ++iter) {

sum += *iter;

}

}

因此,使用嵌套依赖的类型名称时,都需要使用typename指定它是一种类型。

例外嵌套依赖名称在基类列表中,或者在成员初始化列表中时,不能使用typename。

template

class Drived: public Base::Nested { // 基类列表,不要使用typename

public:

explicit Derived(int x): Base::Nested(x) { // 成员初始化列表,不要使用typename

typename Base::Nested temp;

...

}

...

};

另外一些注意点

1、嵌套从属名称(nested dependent names)假如template内出现的名称如果依赖于某个模板参数,则称其为从属名称(dependent names),如果从属名称在class内呈嵌套状则称之为嵌套从属名称(nested dependent names)。

例如:

templaet void myPrint(const T& t){

t::const_iterator iter(t.begin());

}

假设模板参数列表中的参数表示一个容器类型,则我们知道t::const_iterator一个依赖模板参数并且在容器内部,所以t::const_iterator是一个嵌套从属名称。

在我们知道t是什么之前没有办法可以知道t::const_iterator是否是一个类型,因为有还可能是个静态(static)成员变量,考虑下面的例子:

template void myPrint(const T& t){

t::const_iterator * x;

}

如果const_iterator是t的静态成员变量,则上面的t::const_iterator * x;中的*表示乘法,如果是个类型则表示声明一个指向t::const_iterator类型的指针。

从而给编译器造成困惑(因为我们不知道t是什么)。

C++有个规定:当解析器在模板中遇到一个嵌套从属名称时便假定这个名称不是类型,除非你用关键字typename指定它是:

template void myPrint(const T& t){

typename t::const_iterator * x; //这样便不会造成困惑了}

同理不仅在内部,在参数列表里也是:

template void f(const T& t, typename T::const_iterator cit){

//T不是嵌套从属名称,而T::const_iterator是,所以要在T::const_iterator前面加上typename //....}

2、是嵌套从属名称但不用加typename的两种情况基类列表(base list)和成员初始化列表(member initializaiton list)

template class Derived: public Base::Nested { //基类列表中不允许使用typenamepublic:

explicit Derived(int x): Base::Nested(int x){ //初始化列表中不允许使用typename typename Base::Nested temp; //嵌套从属名称(既不在基类列表中又不在初始化列表中)前面必须要加typename }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值