C++ - 结合typedef和typename的语句含义

77
在一个C++头文件中,我看到了这段代码:
typedef typename _Mybase::value_type value_type;

现在,据我理解,引用Schildt的《C++完全参考手册》所述,关键字typename可以被替换为class。第二次使用typename是为了告诉编译器,在模板声明中使用的名称是类型名称而不是对象名称。
同样地,您可以使用关键字typedef定义新的数据类型名称。您实际上并没有创建一个新的数据类型,而是为现有类型定义一个新名称。
然而,您能否解释一下上面这行代码的含义,其中typedef和typename组合在一起?语句中的“::”表示什么意思?

1
typenametypedef 内外具有相同的用途。一个更加现实(有点)的例子可以是 typedef typename std::vector<T>::iterator Iter; - chris
8
哦天啊,Schildt 又回来了。现在就把那本书烧了吧。 - chris
2
这三个不相关的C++特性是什么,它们没有在我的书中提到? - Lightness Races in Orbit
6
很遗憾,很多那些所谓的“事实”是错误的。 - Lightness Races in Orbit
4
“Typename可以被关键字class代替”是错误的。令人惊讶的是,Schildt的著作中经常出现这样的随机引用,但其实不正确。 - R. Martinho Fernandes
显示剩余9条评论
2个回答

84

typedef 用于定义你的代码中使用的新类型,就像一个简写。

typedef typename _MyBase::value_type value_type;
value_type v;
//use v

在这里使用typename告诉编译器value_type是一个类型而不是_MyBase的静态成员。

::是类型的作用域。它有点像“属于”,所以value_type“属于”_MyBase,也可以理解为包含关系。


18
这里需要使用'typename'吗? - johngreen
8
这取决于上下文。如果_MyBase依赖于模板参数,那么是的(如果_MyBase是模板类型),否则您就不必这样做。如果您对上下文感到困惑,编译器会通过给出错误来帮助您。 - pippin1289
5
当_MyBase是模板类型时,为什么需要使用typename?而当_MyBase不是模板类型时,为什么不需要使用typename?当_MyBase是模板类型时,编译器无法确定_MyBase是否有一个名为type的成员类型。使用typename可以告诉编译器_MyBase::type是一个类型,而不是成员函数或变量。当_MyBase不是模板类型时,因为不存在嵌套从属类型,因此不需要使用typename关键字。 - Guokas
4
大致上来说,这是因为编译器在模板类型被使用(实例化)之前无法查看其内部。因此,为了使语法有效,程序员必须明确value_type是否为类型,即通过typename或不使用该关键字来澄清它是成员变量还是方法。 - pippin1289

7

typename 表示 _Mybase::value_type 是一个类型名称,所以 typedef 可以依赖于这个事实。


13
如果我不包含它会发生什么变化?它不能编译,或者有一些警告缺失吗?我认为 typedef A B; 在所有情况下都能正常工作。 - masterxilo
7
如果有人能回答@masterxilo的评论,那就太好了,因为我也正想着同样的事情。 - RastaJedi
2
在Visual Studio中,至少在这种情况下,似乎不需要typename。 除非您当前定义的类是模板化的,否则放置它甚至是错误的。 typedef int Int; template<typename T> struct B { typedef typename Int IInt; }; 是可以的,但是 typedef int Int; struct B { typedef typename Int IInt; }; 不行。 - masterxilo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接