• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

C++的template模板中class与typename关键字的区别分析

c++ 搞代码 4年前 (2022-01-06) 44次浏览 已收录 0个评论

这篇文章中我们来谈一谈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 myPrin<a style="color:transparent">来源gao($daima.com搞@代@#码网</a>t(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  } }

以上就是C++的template模板中class与typename关键字的区别分析的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:C++的template模板中class与typename关键字的区别分析

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址