设计公司网站运营,吉林建筑大学本科招生网,网站建站去哪找客户,如何做行业网站标识符是一个由程序员定义的名称#xff0c;为标识区别变量、函数和数据类型等#xff0c;代表程序的某些元素#xff0c;变量名就是标识符的一个展现。 作用域讨论的是标识符的有效范围#xff0c;可见性讨论的是标识符是否可以被引用。在一个函数中声明的变量就只能在这个…标识符是一个由程序员定义的名称为标识区别变量、函数和数据类型等代表程序的某些元素变量名就是标识符的一个展现。 作用域讨论的是标识符的有效范围可见性讨论的是标识符是否可以被引用。在一个函数中声明的变量就只能在这个函数中起作用这就是受变量的作用域和可见性的限制。作用域与可见性既相互联系又存在很大差异。
1.作用域
作用域是一个标识符在程序正文中有效的区域。C中标识符的作用域有函数原型作用域、局部作用域块作用域、类作用域和命名空间作用域。
1函数原型作用域
函数原型作用域是C程序中最小的作用域。在函数原型中一定要包含形参的类型说明。在函数原型声明时形式参数的作用范围就是函数原型作用域。 例如有以下函数声明
double area(double radius);标识符radius的作用或称有效范围就在函数area形参列表的左右括号之间在程序的其他地方不能引用这个标识符。因此标识符radius的作用域称为函数原型作用域。 【注意】由于在函数原型的形参列表中起作用的只是形参类型标识符并不起作用因此是允许省去的。但考虑到程序可读性通常还是要在函数原型声明时给出形参标识符。
2局部作用域
【例】 这里函数fun的形参列表中声明了形参a在函数体内声明了变量b并且用a的值初始化b。接下来在if语句中又声明了变量c。abc都具有局部作用域只是它们分别属于不同的局部作用域。 函数形参列表中形参的作用域从形参列表中的声明处开始到整个函数体结束是之处为止。因此形参a的作用域从a的声明处开始直到fun函数的结束处为止。 函数体内声明的变量其作用域从声明处开始一直到声明所在的块结束为止。 所谓块就是一对大括号括起来的一段程序。在这个例子中函数体是一个块if语句后的分支体又是一个较小的块二者是包含关系。因此变量b的作用域从声明处开始到它所在的块即整个函数体结束处为止而变量c的作用域从声明处开始到它所在的块即分支体结束为止。 具有局部作用域的变量也称为局部变量。
3类作用域
类可以被看成是一组有名成员的集合类X的成员m具有类作用域对m的访问方式有如下三种 ①如果X的成员函数中没有声明同名的局部作用域标识符那么在该函数内可以直接访问成员m。也就是说类的数据成员m在这样的函数中都起作用。 X的成员函数中没有声明与类中数据成员同名的局部作用域标识符的情况
class X
{
public:X(int m 0):m(m){}int getM(){//int m7;return m;}
private:int m;
};
int main()
{X b(5);b.getM();cout b.getM() endl;
}运行结果 X的成员函数中声明了与类中数据成员同名的局部作用域标识符的情况
class X
{
public:X(int m 0):m(m){}int getM(){int m7;return m;}
private:int m;
};
int main()
{X b(5);b.getM();cout b.getM() endl;
}运行结果 ②通过表达式x.m或者X::m。这正是程序中访问对象的最基本方法。X::m的方式用于访问类的静态成员。 ③通过ptr-m这样的表达式其中ptr为指向X类的一个对象指针。 C中类及其对象还有其他特殊的访问和作用域规则。
4命名空间作用域
命名空间的概念 在C/C中变量、函数和类都是大量存在的这些变量、函数和类的名称将都存在于全局作用域中可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化以避免命名冲突或名字污染namespace关键字的出现就是针对命名空间的。 命名空间的定义 定义命名空间需要使用到namespace 关键字这个关键字的作用就是定义一个命名空间。 命名空间的语法形式如下
namespace 命名空间名
{命名空间内的各种声明(函数声明、类声明...)
}一个命名空间确定了一个命名空间的作用域凡是在该命名空间之内声明的、不属于前面所述各个作用域的标识符都属于该命名空间的作用域。在命名空间你内部可以直接引用当前命名空间中声明的标识符如果需要引用其他命名空间的标识符需要使用下面的语法
命名空间名::标识符名例如 定义一个命名空间
namespace SomeNs
{class SomeClass{...};void somemeFunc(){...}
}如果需要引用类名SomeClass或者函数名somemeFunc需要使用下面的方式
SomeNs::SomeClass obj1;//声明一个SomeNs::SomeClass型的对象obj1有时在标识符前总使用这样的命名空间限定会显得过于冗长为了解决这一问题C又提供了using语句using语句有两种形式
using 命名空间::标识符名;//1
using namespace 命名空间名;//2第一种形式将指定的命名空间中的标识符暴露在当前的作用域中使得在当前作用域中可以之间引用该标识符第二种形式将指定命名空间内的所有标识符暴露在当前的作用域中使得在当前作用域中可以直接引用该命名空间内的任何标识符。 事实上C标准程序库的所有标识符都被声明在std命名空间内平时所用到的cin、cout、endl等标识符都是如此因此前面的程序中都使用了using namespace std;。如果去掉这条语句则引用相应的标识符需要使用std::cin、std::cout、std::endl这样的语法。 命名空间也允许嵌套例如
namespace OuterNs
{namespace InnerNs{class SomeClass{...};}
}引用其中的SomeClass类需要使用OuterNs::InnerNs::SomeClass的语法形式。 此外还有两类特殊的命名空间——全局命名空间和匿名命名空间。全局命名空间就是默认的命名空间在显式声明的命名空间之外的标识符都在一个全局命名空间中。匿名命名空间是一个需要显式声明的没有名字的命名空间声明方式如下
namespace
{匿名命名空间内的各种声明(函数声明、类声明、......)
}在包含多个源文件的工程中匿名命名空间常常被用来屏蔽不希望暴露给其他源文件的标识符这是因为每个源文件的命名空间是彼此不同的在一个源文件中没有办法访问其他源文件的匿名命名空间。 【例】作用域实例以下声明的全局变量就具有命名空间作用域它在整个文件中都有效。
int i;//在全局命名空间中的全局变量
namespace Ns
{int j;//在Ns命名空间中的全局变量
}
int main()
{i 5;//为全局变量i赋值Ns::j 6;//为Ns命名空间中的全局变量j赋值{ //子块1using namespace Ns;//使得在当前块中可以直接引用Ns命名空间中的标识符int a; //局部变量局部作用域a 7; cout a a endl;//输出7int i 8; //局部变量局部作用域cout j j endl;//输出6cout i i endl;//输出8}cout i i endl;//输出5return 0;
}运行结果 在上面的例子中变量i具有命名空间作用域它属于全局命名空间其有效作用范围到文件尾才结束。在主函数开始处给这个具有命名空间作用域的变量赋初值5接下来在子块1中又声明了同名变量并赋初值8。所以第一次输出i的值为8这是因为具有局部作用域的变量i把具有命名空间作用域的变量i隐藏了具有命名空间作用域的变量i变得不可见。在程序运行到子块1结束后变量i进行第二次输出时输出的就是具有命名空间作用域的变量i的值5。变量j也具有命名空间作用域它被声明在命名空间Ns当中在主函数中通过Ns::j的方式引用并为其赋初值接下来在块1中通过using namespace Ns使得命名空间的标识符可以在该块中被直接引用因此输出j的值时可以直接使用标识符j。 具有命名空间作用域的变量也称为全局变量。
2.可见性
从标识符引用的角度来看标识符的有效范围即标识符的可见性。程序运行到某一点能够引用到的标识符就是该处可见的标识符。
不同作用域之间的关系
命名空间作用域最大接下来依次是类作用域和局部作用域。如下图所示 可见性表示从内层作用域向外层作用域“看”时能看到什么可见性和作用域之间有着密切的关系。
作用域的可见性的一般规则如下
1标识符要声明在前引用在后。 2在同一作用域中不能声明同名的标识符。 3在没有互相包含关系的不同的作用域中声明的同名标识符互不影响。 4如果两个或多个具有包含关系的作用域中声明了同名标识符则外层的标识符在内层不可见。 【例】
int i;//在全局命名空间中的全局变量
namespace Ns
{int j;//在Ns命名空间中的全局变量
}
int main()
{i 5;//为全局变量i赋值Ns::j 6;//为Ns命名空间中的全局变量j赋值{ //子块1using namespace Ns;//使得在当前块中可以直接引用Ns命名空间中的标识符int i 8; //局部变量局部作用域cout i i endl;//输出8}cout i i endl;//输出5return 0;
}运行结果
上例是命名空间作用域与局部作用域互相包含的实例在主函数内块1之外可以引用具有该命名空间作用域的变量也就是说它是可见的。当程序进入块1后就只能引用具有局部作用域的同名变量具有命名空间作用域的同名变量被隐藏了。这也是为什么两次输出的变量i的值不同。 【注意】作用域和可见性的原则不只适用于变量名也适用于其他各种标识符包括常量名、用户定义的类型名、函数名、枚举类型的取值等。