理解混淆typedef语法
考虑下面的代码片段
typedef int type; int main() { type *type; // why is it allowed? type *k ;// which type? }
我得到一个错误'k' is not declared in this scope
。 编译器将type *k
parsing为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
,当然仍然可用。
这是令人困惑,但这是获得访问type
variables的唯一方法。 如果你想使用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_
, name
, NAME
等 – 所有这些不要吸引我。
至于你的代码,由于在范围内( 对象 type
声明之后), type
已经是一个variables,types不能直接引用。 但我认为这应该编好,按照标准:
typedef int type; int main() { type *type; // why is it allowed? ::type *k ;// which type? }
演示: http : //ideone.com/chOov