作者:思多雅[天行健] 2008-10-11发布
一、什么是声明
在我们编程的时候,经常要使用一些常量和变量,告诉编译器那些是常量,那些是变量,都是些什么常量或变量的一个过程,就是我们常说的声明,其中也就包括我们为常量和变量“取名字”。
拿个示列:
int i;
表示说,我们告诉编译器说,我这里要用一个“数字”的变量,它的名字叫“i”。
另外,编程里还有个名词叫“定义”,就是指为“声明”出来的变量/常量的“名字”,如上面的“i”分配一个内存空间。
-------思多雅[天行健]版权所有,首发太平洋论论坛,转载请注明-------
二、C#的声明
C#程序中的声明定义了程序的重要声明。C#程序用名称空间来组织,它可以包含类型声明和嵌套声明。类型声明用来定义类、结构、接口、联合和代表。在类型定义中被允许的的成员种类要根据类型声明的形式决定。例如,类的声明可以包含实例构造函数、析构函数、静态构造函数、常数、域、方法、属性、事件、索引、操作符和嵌套类型。
一个声明在声明所属的声明域定义了一个名称。除了重载构造函数、方法、索引和操作符名称,在一个声明域中有两个或更多介绍有相同名称成员的声明时,是错误的。对一个声明域中,包含有相同名称的不同种类成员是永远不可能的。例如,一个声明域中不能包括有相同名称的域和方法。
这里有许多种不同类型的声明域,如下所示。
* 在所有程序的源文件中,不包括嵌套名称空间声明的名称空间成员声明都是一个单独的组合声明域,称为全局声明域。
* 在所有程序的源文件中,名称空间成员声明和有相同完整正确的名称空间名称的名称空间声明都是一个单独的组合声明域。
* 每个类,结构或接口声明都会创建一个新的声明域。名称通过类成员声明、结构成员什么或接口成员声明介绍到这个声明域中。除了重载构造函数声明和静态构造函数声明,一个类或结构成员声明不能引入与类或结构名称相同的成员。一个类,结构或接口允许方法和索引的重载。此外,一个类或结构允许构造函数和操作符的重载声明。例如,一个类、结构或接口可能会包含多个用相同名称声明的方法,而在他们各自签名中提供了不同的方法声明。注意基类不影响类的声明域。而基本接口不影响一个接口的声明域。这样,一个派生的类或接口可以用和继承的成员相同的名称声明一个成员。这样的一个成员被称为隐藏了继承的成员。
* 每个枚举声明创建一个新的声明域。名称通过枚举成员声明介绍到声明域中。
* 每个块或者转换块为局部变量创建一个分立声明域。名称通过局部变量声明被引入到这个声明域。
如果一个块是构造函数或方法声明的主体,在形参列表中声明的参数是这个块的局部变量声明域的成员。块的局部变量声明域包括任何嵌套块。因而,在一个嵌套块中不太可能用与嵌套块中的局部变量有相同名称声明一个局部变量。
* 每个块或转换块为标签创建一个分立的声明域。名称通过标签声明被引入到这个声明域,而名称通过goto 声明引入到这个声明域。块的局部变量声明域包括任何嵌套块。因而,在一个嵌套块中不太可能用与嵌套块中的标签相同名称声明一个标签。 在名称被声明的文本顺序通常并不重要。特别是,文本顺序对于声明和使用名称空间、类型、常数、方法、属性、事件、索引、操作符、构造函数、析构函数和静态构造函数来说并不重要。声明顺序在下面的途径中才是重要的:
* 域声明和局部变量的声明顺序决定了他们的初始化是按什么顺序执行。
* 局部变量必须在他们被使用前定义。
* 当常数表达式数值被忽略,枚举成员声明的声明顺序是重要的。
名称空间的声明域是“开放的”,而两个有相同的完全名称的名称空间声明将放到相同的名称空间空间中。例如
namespace Megacorp.Data
{
class Customer
{
...
}
}
namespace Megacorp.Data
{
class Order
{
...
}
}
上面声明的两个名称空间声明捐献到相同的声明域,这里声明了两个有完全合格名称的类Megacorp.Data.Customer 和Megacorp.Data.Order 。因为两个声明属于相同的声明域,如果每个都包含一个对相同名称的类的声明,就会产生错误。
块的声明域包括任何嵌套块。这样,在下面的例子中,方法F 和G 有错误,因为名称I 已经在outer 块中声明了,就不能再在inner 块中声明。然而,由于两个i 是在分立的非嵌套块中声明的,方法H 和I是有效的。
class A
{
void F() {
int i = 0;
if (true) {
int i = 1;
}
}
void G() {
if (true) {
int i = 0;
}
int i = 1;
}
void H() {
if (true) {
int i = 0;
}
if (true) {
int i = 1;
}
}
void I() {
for (int i = 0; i < 10; i++)
H();
for (int i = 0; i < 10; i++)
H();
}
}
-------思多雅[天行健]版权所有,首发太平洋论论坛,转载请注明-------
三、小知识:
1、C语言及C++的声明
相信熟悉C语言的人都知道,在C中如果要将一组不同类型的变量组合在一起使用就会用到struct关键字。与其想配合的还有一组函数供其调用,以实现该struct的不同功能。但是有一点,那就是所有这些函数对于该struct以外的变量也都是可见的,一样可以调用这个函数。这样是很不安全的,对于程序设计的模块化也没有什么好处。
C++的声明是在C语言的改进,C++的第一步就是将函数放到struct里面,作为“成员函数”。这样就带来了新的问题:各个struct中的函数可以重名,在定义这个函数时,需要完全指定它是哪一个。为了完成这个指定任务, C + +有一个新的运算符: :,即范围分解运算符(用来指定该函数的执行范围,即是哪个struct中的)。
在C++中,将函数放进结构中是对C的一种根本改变。在C 中,结构是数据的凝聚,它将数据捆绑在一起,使得我们可以将它们看作一个包。但这除了能使程序设计方便之外,别无其他好处。这些结构上的运算可以用在别处。然而将函数也放在这个包内,结构就变成了新的创造物,它既能描述属性(就像C中的struct 能做的一样),又能描述行为,这就形成了对象的概念。对象是一个独立的有约束的实体,有自己的记忆和活动。在C++ 中,对象只是一个变量,最纯的定义是“存储的一个区域”。它是能存放数据的空间,并隐含着还有在这些数据上的运算。将数据连同函数捆绑在一起,这一点就允许创建新的类型。这常常被称为封装。
然而,我们会看到在对象上完成运算的方法有所不同。
object.member_function(arglist)是对一个对象“调用一个成员函数”。而在面向对象的用法中,也称之为“向一个对象发送消息”。这样,对于stash K,语句K.add(&i)“发送消息给K”,也就是说,“对自己add( )”。事实上,面向对象程序设计可以总结为一句话,“向对象发送消息”。需要做的所有事情就是创建一束对象并且给它们发送消息。当然,问题是勾画出我们的对象和消息是什么,但如果完成了这些,C++ 的实现就直截了当了。
一个结构的大小是它的所有成员大小的和。有时,当一个struct 被编译器处理时,会增加额外的字节以使得捆绑更整齐,这主要是为了提高执行效率。
另外,用sizeof可以计算出struct的内存大小。
下面我们来看看相应的例子:
//计算struct内存
#include <stdio.h>
struct A1
{
int i[100];
};
struct A2
{
void x();
};
void main(void)
{
printf(“size of struct A is %d/n”, sizeof(A1);
printf(“size of struct B is %d/n”, sizeof(A2);
}
第一句printf会打印出200,而第二句则会打印出一个不确定的非零值。
因为这个声明这个在C中不合法,但是在C++中是合法的。
你可以拿这个对比一下C#的声明。看看有些什么不同呢?
一、什么是声明
在我们编程的时候,经常要使用一些常量和变量,告诉编译器那些是常量,那些是变量,都是些什么常量或变量的一个过程,就是我们常说的声明,其中也就包括我们为常量和变量“取名字”。
拿个示列:
int i;
表示说,我们告诉编译器说,我这里要用一个“数字”的变量,它的名字叫“i”。
另外,编程里还有个名词叫“定义”,就是指为“声明”出来的变量/常量的“名字”,如上面的“i”分配一个内存空间。
-------思多雅[天行健]版权所有,首发太平洋论论坛,转载请注明-------
二、C#的声明
C#程序中的声明定义了程序的重要声明。C#程序用名称空间来组织,它可以包含类型声明和嵌套声明。类型声明用来定义类、结构、接口、联合和代表。在类型定义中被允许的的成员种类要根据类型声明的形式决定。例如,类的声明可以包含实例构造函数、析构函数、静态构造函数、常数、域、方法、属性、事件、索引、操作符和嵌套类型。
一个声明在声明所属的声明域定义了一个名称。除了重载构造函数、方法、索引和操作符名称,在一个声明域中有两个或更多介绍有相同名称成员的声明时,是错误的。对一个声明域中,包含有相同名称的不同种类成员是永远不可能的。例如,一个声明域中不能包括有相同名称的域和方法。
这里有许多种不同类型的声明域,如下所示。
* 在所有程序的源文件中,不包括嵌套名称空间声明的名称空间成员声明都是一个单独的组合声明域,称为全局声明域。
* 在所有程序的源文件中,名称空间成员声明和有相同完整正确的名称空间名称的名称空间声明都是一个单独的组合声明域。
* 每个类,结构或接口声明都会创建一个新的声明域。名称通过类成员声明、结构成员什么或接口成员声明介绍到这个声明域中。除了重载构造函数声明和静态构造函数声明,一个类或结构成员声明不能引入与类或结构名称相同的成员。一个类,结构或接口允许方法和索引的重载。此外,一个类或结构允许构造函数和操作符的重载声明。例如,一个类、结构或接口可能会包含多个用相同名称声明的方法,而在他们各自签名中提供了不同的方法声明。注意基类不影响类的声明域。而基本接口不影响一个接口的声明域。这样,一个派生的类或接口可以用和继承的成员相同的名称声明一个成员。这样的一个成员被称为隐藏了继承的成员。
* 每个枚举声明创建一个新的声明域。名称通过枚举成员声明介绍到声明域中。
* 每个块或者转换块为局部变量创建一个分立声明域。名称通过局部变量声明被引入到这个声明域。
如果一个块是构造函数或方法声明的主体,在形参列表中声明的参数是这个块的局部变量声明域的成员。块的局部变量声明域包括任何嵌套块。因而,在一个嵌套块中不太可能用与嵌套块中的局部变量有相同名称声明一个局部变量。
* 每个块或转换块为标签创建一个分立的声明域。名称通过标签声明被引入到这个声明域,而名称通过goto 声明引入到这个声明域。块的局部变量声明域包括任何嵌套块。因而,在一个嵌套块中不太可能用与嵌套块中的标签相同名称声明一个标签。 在名称被声明的文本顺序通常并不重要。特别是,文本顺序对于声明和使用名称空间、类型、常数、方法、属性、事件、索引、操作符、构造函数、析构函数和静态构造函数来说并不重要。声明顺序在下面的途径中才是重要的:
* 域声明和局部变量的声明顺序决定了他们的初始化是按什么顺序执行。
* 局部变量必须在他们被使用前定义。
* 当常数表达式数值被忽略,枚举成员声明的声明顺序是重要的。
名称空间的声明域是“开放的”,而两个有相同的完全名称的名称空间声明将放到相同的名称空间空间中。例如
namespace Megacorp.Data
{
class Customer
{
...
}
}
namespace Megacorp.Data
{
class Order
{
...
}
}
上面声明的两个名称空间声明捐献到相同的声明域,这里声明了两个有完全合格名称的类Megacorp.Data.Customer 和Megacorp.Data.Order 。因为两个声明属于相同的声明域,如果每个都包含一个对相同名称的类的声明,就会产生错误。
块的声明域包括任何嵌套块。这样,在下面的例子中,方法F 和G 有错误,因为名称I 已经在outer 块中声明了,就不能再在inner 块中声明。然而,由于两个i 是在分立的非嵌套块中声明的,方法H 和I是有效的。
class A
{
void F() {
int i = 0;
if (true) {
int i = 1;
}
}
void G() {
if (true) {
int i = 0;
}
int i = 1;
}
void H() {
if (true) {
int i = 0;
}
if (true) {
int i = 1;
}
}
void I() {
for (int i = 0; i < 10; i++)
H();
for (int i = 0; i < 10; i++)
H();
}
}
-------思多雅[天行健]版权所有,首发太平洋论论坛,转载请注明-------
三、小知识:
1、C语言及C++的声明
相信熟悉C语言的人都知道,在C中如果要将一组不同类型的变量组合在一起使用就会用到struct关键字。与其想配合的还有一组函数供其调用,以实现该struct的不同功能。但是有一点,那就是所有这些函数对于该struct以外的变量也都是可见的,一样可以调用这个函数。这样是很不安全的,对于程序设计的模块化也没有什么好处。
C++的声明是在C语言的改进,C++的第一步就是将函数放到struct里面,作为“成员函数”。这样就带来了新的问题:各个struct中的函数可以重名,在定义这个函数时,需要完全指定它是哪一个。为了完成这个指定任务, C + +有一个新的运算符: :,即范围分解运算符(用来指定该函数的执行范围,即是哪个struct中的)。
在C++中,将函数放进结构中是对C的一种根本改变。在C 中,结构是数据的凝聚,它将数据捆绑在一起,使得我们可以将它们看作一个包。但这除了能使程序设计方便之外,别无其他好处。这些结构上的运算可以用在别处。然而将函数也放在这个包内,结构就变成了新的创造物,它既能描述属性(就像C中的struct 能做的一样),又能描述行为,这就形成了对象的概念。对象是一个独立的有约束的实体,有自己的记忆和活动。在C++ 中,对象只是一个变量,最纯的定义是“存储的一个区域”。它是能存放数据的空间,并隐含着还有在这些数据上的运算。将数据连同函数捆绑在一起,这一点就允许创建新的类型。这常常被称为封装。
然而,我们会看到在对象上完成运算的方法有所不同。
object.member_function(arglist)是对一个对象“调用一个成员函数”。而在面向对象的用法中,也称之为“向一个对象发送消息”。这样,对于stash K,语句K.add(&i)“发送消息给K”,也就是说,“对自己add( )”。事实上,面向对象程序设计可以总结为一句话,“向对象发送消息”。需要做的所有事情就是创建一束对象并且给它们发送消息。当然,问题是勾画出我们的对象和消息是什么,但如果完成了这些,C++ 的实现就直截了当了。
一个结构的大小是它的所有成员大小的和。有时,当一个struct 被编译器处理时,会增加额外的字节以使得捆绑更整齐,这主要是为了提高执行效率。
另外,用sizeof可以计算出struct的内存大小。
下面我们来看看相应的例子:
//计算struct内存
#include <stdio.h>
struct A1
{
int i[100];
};
struct A2
{
void x();
};
void main(void)
{
printf(“size of struct A is %d/n”, sizeof(A1);
printf(“size of struct B is %d/n”, sizeof(A2);
}
第一句printf会打印出200,而第二句则会打印出一个不确定的非零值。
因为这个声明这个在C中不合法,但是在C++中是合法的。
你可以拿这个对比一下C#的声明。看看有些什么不同呢?