C 箴言:理解typename的两个含义
2008-02-23 05:27:14来源:互联网 阅读 ()
template<class T> class Widget; // uses "class" template<typename T> class Widget; // uses "typename" |
答案:没什么不同。在声明一个 template type parameter(模板类型参数)的时候,class 和 typename 意味着完全相同的东西。一些程式员更喜欢在任何的时间都用 class,因为他更容易输入。其他人(包括我本人)更喜欢 typename,因为他暗示着这个参数不必要是个 class type(类类型)。少数研发者在任何类型都被允许的时候使用 typename,而把 class 保留给仅接受 user-defined types(用户定义类型)的场合。但是从 C 的观点看,class 和 typename 在声明一个 template parameter(模板参数)时意味着完全相同的东西。
然而,C 并不总是把 class 和 typename 视为等同的东西。有时您必须使用 typename。为了理解这一点,我们不得不讨论您会在一个 template(模板)中涉及到的两种名字。
假设我们有一个函数的模板,他能取得一个 STL-compatible container(STL 兼容容器)中持有的能赋值给 ints 的对象。进一步假设这个函数只是简单地打印他的第二个元素的值。他是个用糊涂的方法实现的糊涂的函数,而且就像我下面写的,他甚至不能编译,但是请将这些事先放在一边——有一种方法能发现我的愚蠢:
template<typename C> // print 2nd element in void print2nd(const C& container) // container; { // this is not valid C ! if (container.size() >= 2) { C::const_iterator iter(container.begin()); // get iterator to 1st element iter; // move iter to 2nd element int value = *iter; // copy that element to an int std::cout << value; // print the int } } |
我突出了这个函数中的两个 local variables(局部变量),iter 和 value。iter 的类型是 C::const_iterator,一个依赖于 template parameter(模板参数)C 的类型。一个 template(模板)中的依赖于一个 template parameter(模板参数)的名字被称为 dependent names(依赖名字)。当一个 dependent names(依赖名字)嵌套在一个 class(类)的内部时,我称他为 nested dependent name(嵌套依赖名字)。C::const_iterator 是个 nested dependent name(嵌套依赖名字)。实际上,他是个 nested dependent type name(嵌套依赖类型名),也就是说,一个涉及到一个 type(类型)的 nested dependent name(嵌套依赖名字)。
print2nd 中的另一个 local variable(局部变量)value 具备 int 类型。int 是个不依赖于任何 template parameter(模板参数)的名字。这样的名字以 non-dependent names(非依赖名字)闻名。(我想不通为什么他们不称他为 independent names(无依赖名字)。假如,像我相同,您发现术语 "non-dependent" 是个令人厌恶的东西,您就和我产生了共鸣,但是 "non-dependent" 就是这类名字的术语,所以,像我相同,转转眼睛放弃您的自我主张。)
nested dependent name(嵌套依赖名字)会导致解析困难。例如,假设我们更加愚蠢地以这种方法开始 print2nd:
template<typename C> void print2nd(const C& container) { C::const_iterator * x; ... } |
这看上去似乎是我们将 x 声明为一个指向 C::const_iterator 的 local variable(局部变量)。但是他看上去如此仅仅是因为我们知道 C::const_iterator 是个 type(类型)。但是假如 C::const_iterator 不是个 type(类型)呢?假如 C 有一个 static data member(静态数据成员)碰巧就叫做 const_iterator 呢?再假如 x 碰巧是个 global variable(全局变量)的名字呢?在这种情况下,上面的代码就不是声明一个 local variable(局部变量),而是成为 C::const_iterator 乘以 x!当然,这听起来有些愚蠢,但他是可能的,而编写 C 解析器的人必须考虑任何可能的输入,甚至是愚蠢的。
直到 C 成为已知之前,没有任何办法知道 C::const_iterator 到底是不是个 type(类型),而当 template(模板)print2nd 被解析的时候,C 还不是已知的。C 有一条规则解决这个歧义:假如解析器在一个 template(模板)中碰到一个 nested dependent name(嵌套依赖名字),他假定那个名字不是个 type(类型),除非您用其他方式告诉他。缺省情况下,nested dependent name(嵌套依赖名字)不是 types(类型)。(对于这条规则有一个例外,我待会儿告诉您。)
记住这个,再看看 print2nd 的开头:
template<typename C> void print2nd(const C& container) { if (container.size() >= 2) { C::const_iterator iter(container.begin()); // this name is assumed to ... // not be a type |
这为什么不是合法的 C 现在应该很清楚了。iter 的 declaration(声明)仅仅在 C::const_iterator 是个 type(类型)时才有意义,但是我们没有告诉 C 他是,而 C 就假定他不是。要想转变这个形势,我们必须告诉 C C::const_iterator 是个 type(类型)。我们将 typename 放在紧挨着他的前面来做到这一点:
template<typename C> // this is valid C void print2nd(const C& container) { if (container.size() >= 2) { typename C::const_iterator iter(container.begin()); ... } 标签: 版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 上一篇: C 对象布局及多态实现探索之虚继承 下一篇: C 箴言:如何访问模板化基类中的名字
相关文章
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设 网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源 网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它 服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护 软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷 网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash 热门词条
最新资讯
热门关注
热门标签
|