c++关键字typename区别于class的特殊作用

文章讲述了在c++泛型编程中,关键字typename用于明确指示模板参数作用域下的名称是类型名而非变量名。在访问依赖于模板类型的嵌套从属名称时,typename必不可少。编译器在处理模板时,需知道typename的使用来正确解析类型和静态成员。
摘要由CSDN通过智能技术生成

在c++泛型编程中,关键字class和typename都可以用来声明模板参数,但在有些情况下,我们必须使用typename

我们知道,在类的成员声明和定义中,作用域运算符::可以用来访问static成员和类型成员,在普通代码中,编译器知道类的定义,因此当我们使用作用域运算符进行访问一个名字时,它知道我们访问的这个名字是一个类型名还是一个static成员,例如,当我们写下string::size_type时,编译器有string的定义,因此它知道size_type是一个类型名

但是在模板代码里,这种情况就会出现一些困难。

现在假定T是一个模板类型参数,当编译器遇到T::mem时,它不会知道mem到底是一个类型名还是一个static数据成员,直到实例化时才会知道,但是编译器为了处理模板,它又必须知道mem代表的到底是一个类型名还是一个数据成员                                    

再比如,我们有这样一段代码:         

template<typename C>
void print2nd(const C& container)
{
    C::const_iterator* x;
    ...
}

在这段代码里,我们使用作用域运算符访问const_iterator,然而由于C是一个模板参数,在没有实例化之前,我们不知道它的具体定义,因此这种情况下访问const_iterator的时候,编译器并不知道const_iterator到底是一个类型名称还是一个static变量(尽管我们希望它是一个类型名,但编译器并不知道),假如编译器将const_iterator认定为一个变量名,那么上述代码C::const_iterator* x就变成了一个名叫const_iterato的变量乘以一个x的变量,而不是一个指针声明

事实上,默认情况下,c++假定通过作用域运算符::访问的名字不是类型,因此,当我们使用一个模板类型参数的类型成员,就必须显示的告诉编译器该名字是一个类型,我们通过typename关键字实现这一点

因此上述代码应该修改为

template<typename C>
void print2nd(const C& container)
{
    typename C::const_iterator* x;//显示告诉编译器const_iterator是一个类型名而不是一个变量名
    ...
}

总的来说,在泛型编程中,typename关键字的作用是为了显示的告诉编译器在一个模板参数作用域下的一个名字是一个类型名而不是一个变量名 

事实上,template内出现的名称如果相依与某个template参数,称之为从属名称,如果从属名称在class内呈现嵌套状,我们称它为嵌套从属名称。C::const_iterator就是一个嵌套从属名称。

因此,上述规则的学术说法是,typename必须作为嵌套从属名称的前缀词,但是这个规则有个例外,那就是typename不可以出现在base classes list内的嵌套从属名称之前,也不可以在成员初值列中作为base class的修饰符,如

#include<iostream>
using namespace std;

template<typename T>
class derived :public base<T>::nested {//base class list中不允许"typename"
public:
	explict derived(int x) :base<T>::nested(x)//初始化成员列表中不允许"typename"
	{
		/*
		 base<T>::nested temp是一个嵌套从属名称,
		 且既不在base class list中,也不在初始化成员列表中
		 必须使用typename告诉编译器nested是一个类型名称
		*/
		typename base<T>::nested temp;
		...
	}
	...
};

参考:
《c++ primer》

《effective c++》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值