了解 C++ 之 typename

typename与class都可以用作模板形参定义的关键字,两者无异~~

可是,typename的用途并非仅限于此,如下面的代码:


template
   
   
    
    
void print(const C & container)
{
    C::const_iterator iter(container.begin());
    cout << *iter << endl;
    int value = *iter;
    return;
}

   
   


更正:上述模板参数应该为C!!!!

在上述代码中,iter的类型是C::const_iterator,实际的类型取决于C的类型。const_iterator 同时也是C内部的typedef 类型名。 但是,在此处,编译器的行为不会是你预期的。


为了说明这个问题,定义两个概念,一个是从属名称,一个是非从属名称。


在上述代码中,iter 是依赖于模板参数C的,因此被称为从属名称;

同理,value是内置类型,不依赖于任何模板参数,因此被称为 非从属名称。

 

C++编译器在面对从属名称时,如果此时该从属名称又嵌套了其他类型,如此处的 iter就是C::const_iterator类型,

这里的C::const_iterator 称嵌套从属类型(嵌套于C类型,从属于模板参数C)。编译器在看到这样的代码

时,难免会晕头转向,因为它不知道const_iterator  是C内部定义的类型,还是C内部的成员变量。因此,编译器一致

约定说,对于这样的不负责任的输入,编译器一致将其认为 “这不是个类型”!!显然这就需要在代码中明确地告诉

它,这是个类型,就这样只需要 在 C::const_iterator 前面加上关键字 typename 即可。


这就是必须用到typename的地方。告诉编译器,明确代码的含义,如果觉得很难记住,记住下面这一个例子就可以了:


template <class T>         //可以是class或者是typename,定义模板

void  f( const    C & container  ,   typename C::iterator iter);   //   第一个参数不需要typename,因为它并没有设计嵌套从属类型,它只是个从属类型(因为与C相关), 后面的typename是必须的。



但是,这里似乎有一些恼人的情况,前面提到说,在嵌套从属类型之前,你需要明确的告诉编译器,你需要的是个类型,可是有些

时候,又不能这么做。

比如下面的情况:

1 在类定义的基类列表中出现的嵌套从属类型之前,不能写typename。

2 在成员初值列表中,不能使用typename。


例如下面的例子

template
   
   
    
    
class Derived : public Base
    
    
     
     ::Nested
{
    public:
        explicit Deirved(int x) : Base
     
     
      
      ::Nested(x)
        {
            typename Base
      
      
       
       ::Nested temp;
            ....
        }
};

      
      
     
     
    
    
   
   

总之:

在template声明时,class与typename是等价的。

typename则用在嵌套从属类型定义时,除了在成员初值列以及基类列表中。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值