理解混淆typedef语法

考虑下面的代码片段

typedef int type; int main() { type *type; // why is it allowed? type *k ;// which type? } 

我得到一个错误'k' is not declared in this scope 。 编译器将type *kparsing为type*k之间的乘法。 这个语法不是很混乱吗?

为什么是C ++标准允许的type *type ? 因为语法是这样说的? 为什么?

这个问题实际上是关于什么时候将一个variables名称定义为一个标识符,并且该语言确定它恰好位于声明该variables的代码之后:

 typedef int type; int main() { type t; // type refers to ::type int // type still refers to ::type type; // variable declared, this shadows ::type type + 1; // type is a variable of type int. } 

在其他情况下也有类似的规则,只是决定何时声明标识符。 还有其他类似的情况,例如在一个类的初始化列表中:

 struct test { int x; // declare member test( int x ) // declare parameter (shadows member) : x( // refers to member (parameter is not legal here) x ) // refers to parameter {}; }; 

或者在成员函数定义中的标识符范围内:

 struct test { typedef int type; type f( type ); }; test::type // qualification required, the scope of the return type is // at namespace level test::f( type t ) // but the scope of arguments is the class, no qualification // required. {} 

作为决定的基本原理,我不能告诉你,但它是一致的和简单的。

 type *type; // why is it allowed? 

C ++ 11 3.3.2 / 1说:

一个名称的声明点紧跟其完成声明符(第8条)之后,在其初始化符(如果有)之前,

所以variables名type在使用types名称type之后才被引入; types名称是声明器中type唯一可用的含义。

 type *k ;// which type? 

局部variables名称隐藏全局types名称,所以在这里select。 这在C ++ 11 3.3.10 / 1中有描述:

通过在嵌套声明区域或派生类中显式声明同名,可以隐藏名称。

完全限定的types名称::type ,当然仍然可用。

这是令人困惑,但这是获得访问typevariables的唯一方法。 如果你想使用type type,你可以这样做:

 typedef int type; int main() { type *type; ::type *k ; return 0; } 

这些语法怪物大部分来自与C的向后兼容性。

保持命名空间(不是C ++意义上的,而是variables/types名称空间)的基本原理相当明显:当你不用types名称来污染variables名称空间时,在typedef上的代码就会减less。

假设有一个名为“employee”的variables的预先存在的代码。 如果variables和typedef存在于同一个命名空间中,则使用“typedef struct {} employee;” 会破坏现有的代码,需要更改variables名称(这在IDE之前的日子里更是一个问题)。 但是,如果他们共享一个名字空间,那么在大代码中selecttypes名称时就没有问题,人们也不必担心了。

我认为这可能是因为它为程序员在为他们声明的variablesselect名称时提供了灵活性。 在C#中,可以声明与该types同名的属性:

 //C# code class Manager { public Name Name {get;set;} }; 

当我用C#编写代码时,我发现这个function非常有用。 因为我有更多的名字可供select。 否则,如果我有一个名为Name的types,那么我将无法创build同名的属性,我将被迫select一个不同的名称,比如Name_Name_nameNAME等 – 所有这些不要吸引我。


至于你的代码,由于在范围内( 对象 type声明之后), type已经是一个variables,types不能直接引用。 但我认为这应该编好,按照标准:

 typedef int type; int main() { type *type; // why is it allowed? ::type *k ;// which type? } 

演示: http : //ideone.com/chOov