《Effective C++》读书笔记 条款42:了解typename的双重意义

主要就是要记住typename作为从属嵌套名称的前缀很重要

在template的声明式中,如:

template<class T> class Widget;//使用class
template<typename T> class Widget;//使用“typename”

typename 和class 的意义完全相同。但是与class不同的是typename还有一个意义。

可以看一段书上的代码

template<typename C>
void print2nd(const C& container)
{
    if(container.size()>=2)
    {
        C::const_iterator iter(container.begin());
        ++iter;
        int value = *iter;
        std::cout << value; 
    }
}

首先要明确一点,这段代码不能通过编译。先了解两种名称。

1.非从属名称

不依赖于template参数的名称,称为非从属名称,如value。

 

2.从属名称

在template内出现的名称如果相依于某个template参数,就称之为从属名称。如果从属名称在class内呈嵌套状

我们称之为嵌套从属名称。上述代码中的C::const_iteraotor实际是什么类型取决于C是什么且呈嵌套状,所以是嵌套从属名称。C++在不知道C是什么之前,没有任何办法可以知道C::const_iterator是否为一个类型,它会假设这不是一个类型,所以上述代码无法通过编译。

对于嵌套从属名称,为了让编译器知道它是一个类型需要加上typename,也即是写成

typename C::const_iterator iter(container.begin());

typename的一个重要意义就是必须作为嵌套从属名称的前缀词

template<typename C>   //允许使用“typename”或"class"
void f(const C& container,       //不允许使用“typename”,因为C不是嵌套从属名称
        typename C::iterator iter): //一定要使用typename,因为C::iterator是嵌套从属名称

但是有一个例外,就是typename不能出现在base classes list(声明基类的列表)内的嵌套从属名称之前,也不可以在成员初值列中作为base class修饰符

template<typename T>
class Derived:public Base<T>::Nested //不允许“typename”
{
public:
    explict Derived(int x)
    :Base<T>::Nested(X)                //不允许“typename”
    {
        typename Base<T>::Nested temp; //一定要加“typename”

    }
};

请记住

1.声明template参数时,前缀关键字class和typename可互换

2.请使用关键字typename标识嵌套从属类型名称;但不得在base class lists或 member initialization list内以它作为base class修饰符

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值