营养、健康和生活

理解C/C++语言的声明语法-声明

C/C++语言的声明语法比较晦涩难懂,特翻译Accelerated C++中附录对此的解释,希望对大家有所帮助。

A.1 声明

一些声明可能难以理解,特别是如果声明几个不同类型的名字或者那些指向函数指针的函数。例如在§10.1.1/171中,我们看到

int* p, q;

定义p为一个“整型指针”类型的对象,q为一个整型对象。在§10.1.2/173中,我们看到

double (*get_analysis_ptr())(const vector<Student_info>&);

声明get_analysis_ptr为一个函数,不带任何参数,它返回一个指针,它指向一个函数,它带有一个const vector<Student_info>&参数,返回double。你可以通过重写以清楚的表达这些声明的含义,例如

int* p;

int q;

// 定义analysis_fp为一个函数,它带一个const vector<Student_info>&参// 数,返回一个double类型。

typedef double (*analysis_fp)(const vector<Student_info>&);

analysis_fp get_analysis_ptr();

不幸的是,这种策略不会帮助你阅读其它程序员代码中令人迷惑的声明。

一般,一个声明大致如下

声明语句:声明说明符[声明子[初始化器]] [,声明子[初始化器]]...;

它为每一个声明子声明一个名字。这些名字始于声明开始的地方终于声明作用域结束的地方。一些声明同时也是定义。名字可以声明多次,但是仅能定义一次。如果一个声明分配了存储空间或者定义了类或函数体,那么它也是一个定义。

C++继承了C的声明语法。理解声明的关键是认识到每个声明包含两个部分:一系列声明说明符,它们一起说明一个类型和其它正在声明的特性,紧跟着是零个或多个声明子(每个声明子都可选的有一个关联的初始化器)。根据说明符和声明子的形式,每个声明子都为名字赋予一个类型。

理解声明的第一步是定位说明符和声明子的边界。这很容易:所有的说明符都是关键字或者类型名,因此说明符终止于第一个不是以上类型之一的符号。例如,在

const char * const * const * cp;

很容易找到边界:double是一个类型,左括号后面既不是关键字也不是类型名。因此,声明—说明符只是double,声明子为声明的其它部分,不包含分号。

double (*get_analysis_ptr())(const vector<Student_info>&);

另一个例子,考虑§10.1.2/173中的声明:

第一个既不是关键字也不是类型名的符号是*,因此说明符是const char,唯一的声明子* const * const * cp。

A.1.1 说明符(Specifiers)

我们可以将声明—说明符分成三个部分:类型说明符,存储类说明符,和其它说明符:

声明说明符:{类型说明符|存储类说明符|其它声明说明符}

然而,这种划分仅仅有助于理解,因为声明本身不存在对应的划分:声明—说明符可以以任何次序出现。

类型说明符决定了声明的类型。我们在§A.2/299中讨论内置类型。

type-specifier: char | wchar_t | bool | short | int | long | signed

unsigned | float | double | void | type-name | const | volatile

type-name: class-name | enum-name | typedef-name

const说明符指出这种类型的对象不可以修改,volatile通知编译器变量可能以非语言定义的形式改变,应该避免优化。

注意const既可以出现在说明符部分,这样修改类型,也可以出现在声明子部分,说明一个const指针。这没有任何歧义,因为声明子部分的const总是跟着一个*。

存储类说明符决定变量的位置和生命周期:

storage-class-specifiers: register | static | extern | mutable

register说明符建议编译器通过将此对象放到寄存器中以优化性能。

一般,局部变量在退出声明它们的块(block)时即被销毁;静态变量的值在作用域的入口和出口间会被保存起来。

extern说明符表明当前的声明不是一个定义,隐含着在其它地方存在相应的定义。

mutable存储类仅用于类的数据成员,并且允许修改这些数据成员即使它们是常量对象的成员。

其它声明说明符定义了与类型无关的属性:

other-decl-specifier: friend | inline | virtual | typedef

friend说明符(§12.3.2/216 and §13.4.2/246)改写保护。

内联说明符用于函数定义,提示编译器如果可能内联下面的代码。当展开调用时,函数定义必须出现在那个作用域,因此将内联函数体放到声明函数的头文件中通常是一个好主意。

virtual说明符(§13.2.1/234)仅用于成员函数,表示这个函数是动态绑定的。

typedef说明符(§3.2.2/43)定义类型的同义词。

A.1.2 声明子(Declarators)-未完待续

posted @ 2009-06-10 20:49  dreamliner  阅读(1158)  评论(0编辑  收藏  举报
营养、健康和生活