一、标识符的作用域与可见性

作用域讨论的是标识符的有效范围,可见性讨论的是标识符是否可以被引用。

二、作用域

作用域是一个标识符在程序正文中有效的区域。C++中标识符的作用域有函数原型作用域、局部作用域(块作用域)、类作用域和命名空间作用域。

1.函数原型作用域

C++程序中最小的作用域。在函数原型声明时形式参数的作用范围就是函数原型作用域。

例:

double area{double radius};//标识符radius

注:标识符radius的作用域范围就是在函数area形参列表的左右括号之间,在程序的其他地方不能引用这个标识符。

在函数原型的形参列表中起作用的只是形参类型,标识符并不起作用,因此可以省略标识符,但为了程序的可读性,通常在函数原型声明时给出标识符。

2.局部作用域

函数形参列表中的形参的作用域,从形参列表中的声明处开始,到整个函数体结束之处为止。

函数体内声明的变量,其作用域从声明处开始,一直到声明所在的块结束的大括号为止。

具有局部作用域的变量也称局部变量

void fun(int a){//a的作用域整个函数体
int b=a;//b的作用域大括号里
cin>>b;
if (b<){
int c;//c的作用域 if的大括号里
...
}
}

再例:

#include <iostream>
using namespace std; void anotherFunction() ; //函数原型
int main()
{
int num = ; //主函数main中的num
cout << "In main, num is " << num << endl;
anotherFunction();
cout << "Back in main, num is still " << num << endl;
return ;
}
void anotherFunction()
{
int num = ; //函数anotherFunction中的num
cout << "In anotherFunction, num is " << num << endl;
}

注:虽然有两个名为 num 的变量,但是程序在同一时间只能“看到”其中一个,因为它们在不同的函数中。

两个函数的封闭性质,“{}”分隔变量的作用域。第一个main变量仅在main函数中可见;第二个num仅在anotherFunction函数中可见。

3.类的作用域

类可以被看成一组有名成员的集合,类X的成员m具有类的作用域,对m的访问有如下三种方式:、

①如果X的成员函数中没有声明同名的局部作用域标识符,那么可以直接访问m。也就是说m在这样的函数中都起作用。

Clock globClock;
globClock.showtime();//对象的成员函数具有类的作用域

②通过表达式x.mX::m。这是访问对象成员的最基本方法。X::m的方式用于访问类的静态成员。

void Clock::showtime()

③使用ptr->m,其中ptr为指向X类的一个对象的指针。

Student *student = new Student();
student->show();

4.命名空间作用域

命名空间的语法形式:

namespace 命名空间名{
命名空间内的各种声明(函数声明、类声明......)
}

注:

  一个命名空间确定了一个命名空间的作用域,凡是在该命名空间之内声明的、不属于前面所述各个作用域的标识符,都属于该命名空间作用域。

①如需在该命名空间内需要引用其他命名空间的标识符,语法形式如下:

        命名空间名::标识符

namespace SomeNs{
class SomeClass{...};
}
//如需引用类名SomeClass或函数名someFunc
SomeNs::SomeClass obj1;//声明一个SomeNS型的对象obj1

②为了避免标识符前总使用上面的命名空间限定显得冗长,C++提供了using语句

两种形式

using 命名空间名::标识符名;//将指定的标识符暴露在当前作用域内,使得在当前作用域内可以直接使用该标识符
using namespace 命名空间名;//将指定命名空间内的所有标识符暴露在当前作用域内,使得在该命名空间内可以直接使用任何标识符

③命名空间允许嵌套

namespace OuterNs{
namespace InnerNs{
class SomeClass(...);
}
}

④特殊的命名空间:全局命名空间和匿名命名空间

全局命名空间:是默认的的命名空间,在显式声明的命名空间之外生命的标识符都在一个全局命名空间中

匿名命名空间:是一个需要显式声明的没有名字的命名空间,例如:

namespace{
匿名命名空间内的各种声明(函数声明、类声明、......)
}

二、可见性

定义:程序运行到某一点,能够引用到的标识符,就是该处可见的标识符。

作用域可见性的一般规则如下:

①标识符要声明在前,引用在后

②在同一作用域中不能声明同名的标识符

③在没有互相包含关系的不同的作用域中声明的同名标识符,互不影响

④如果在两个或者多个具有包含关系的作用域中声明了同名标识符,则外层标识符在内层不可见

三、程序实例

#include <iostream>
using namespace std;
int i; //在全局命名空间中的全局变量
namespace Ns{
int j; //在Ns命名空间中的全局变量
}
int main(){
i=; //为全局变量i赋值
Ns::j=; //为全局变量j赋值
{
using namespace Ns; //使当前块中可以直接引用Ns命名空间的标识符
int i; //局部变量,局部作用域
i=;
cout<<"i="<<i<<endl;
cout<<"j="<<j<<endl;
}
cout<<"i="<<i<<endl;
return ;
}

注意:5-1中声明的全局变量就是具有命名空间的作用域,他们在整个文件中都有效。(具有命名空间作用域的变量也成为全局变量

①变量 i 是全局命名空间,有效范围直到文件尾。

②在主函数开始处给 i 赋初值5,接下来又声明了同名变量并赋初值7。第一次输出的结果是7,因为具有局部作用域的变量 i 把具有命名空间作用域的 i 隐藏了,于是具有命名空间作用域的 i 变得不可见。

③第一个块运行结束,输出的 i 的值为7,因为具有局部作用域的 i 不在有效范围之内了,现在处在有效范围内的变量只有具有命名空间作用域的那个变量。

④j被声明在命名空间 Ns 中,在主函数中通过 Ns::j 的方式引用,为其赋值。

C++标识符的作用域与可见性的更多相关文章

  1. C++的标识符的作用域与可见性

    下面是关于C++的标识符的作用域与可见性学习记录,仅供参考 标识符的作用域与可见性 作用域是一个标识符在程序正文中有效的区域. 作用域分类 ①函数原型作用域 ②局部作用域(快作用域) ③类作用域 ④文 ...

  2. PL/SQL变量的作用域和可见性

    变量的作用域和可见性设计变量在块中的位置,不同的位置使得变量具有不同的有效性与可访问性. 变量的作用域是指可以使用变量的程序单元部分,可以是包和子程序包等. 当一个变量在它的作用域中可以用一个不限定的 ...

  3. (C/C++学习笔记) 三. 作用域和可见性

    三. 作用域和可见性 ● 标识符的作用域 标识符的作用域是标识符在程序源代码中的有效范围,从小到大分为函数原型作用域.块作用域(局部作用域),文件作用域(全局作用域). 1. 函数原型作用域 函数原型 ...

  4. C语言中标识符的作用域、命名空间、链接属性、生命周期、存储类型

    Technorati 标签: C,标识符,作用域,命名空间,链接属性,生命周期,存储类型,scope,name space,linkage,storage durations,lifetime 无论学 ...

  5. ISO/IEC 9899:2011 条款6.2.1——标识符的作用域

    6.2.1 标识符的作用域 1.一个标识符可以表示一个对象:一个函数:一个结构体.联合体或枚举的一个标签或一个成员,一个typedef名:一个标签名:一个宏名:或一个宏形参.相同的标识符可以在程序中不 ...

  6. C/C++:作用域、可见性与生存期

    作用域 作用域是用来表示某个标识符在什么范围内有效. C++的作用域主要有四种:函数原型作用域.块作用域.类作用域和文件作用域. 由大到小:文件作用域>类作用域>块作用域>函数原型作 ...

  7. c语言中标识符的作用域

    1.代码块作用域(block scope) 位于一对花括号之间的所有语句称为一个代码块,在代码块的开始位置声明的标识符具有代码块作用域,表示它们可以被这个代码中的所有语句访问.函数定义的形式参数在函数 ...

  8. go 函数的作用域及可见性

    1.全局变量,在程序整个生命周期有效 比如: test.go 中 我们定义 了 a 作为全局变量,那么在这个程序中任何地方都可以调用a, 这个 2. 局部变量,分为两种:1)函数内定义,2)语句块内定 ...

  9. 【转】C语言中标识符的作用域、命名空间、链接属性、生命周期、存储类型

    参考网址:http://blog.csdn.net/zhanglianpin/article/details/41575849 绝对的经典.

随机推荐

  1. MVC框架的主要问题是什么?

    以下是MVC框架的一些主要问题: 对 DOM 操作的代价非常高 程序运行缓慢且效率低下 内存浪费严重 由于循环依赖性,组件模型需要围绕 models 和 views 进行创建

  2. zabbix ALL = NOPASSWD: ALL

  3. php 判断图片文件的真实类型

    /** * * 检测文件的真实类型 * * @param string $srcPath 文件路径 * * @return string $realType 文件真实类型 * */ $imgurl = ...

  4. Flutter StatefulWidget 有状态组件、页面上绑定数据、改变页面数据

    在 Flutter 中自定义组件其实就是一个类,这个类需要继承 StatelessWidget/StatefulWidget. StatelessWidget 是无状态组件,状态不可变的 widget ...

  5. percona-mysql5.7.24使用xtrabackup工具配置主从同步

    主从配置详细过程: 环境准备: 配置好服务器,主从服务器都安装并启动mysql数据库 # 添加读写账号和只读账号,应用配置中,写主库用读写账号,统计从库数据yoga只读账号 grant select, ...

  6. 【转载】 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能

    原文地址: https://www.cnblogs.com/steven-yang/p/5686473.html ------------------------------------------- ...

  7. 有些lambda表达式就可以体现出编程中「Context(上下文)」环境

    编程中什么是「Context(上下文)」?   每一段程序都有很多外部变量.只有像Add这种简单的函数才是没有外部变量的.一旦你的一段程序有了外部变量,这段程序就不完整,不能独立运行.你为了使他们运行 ...

  8. Dart中排除空的情况:

    但是dart的string类型还有另一个方法isNotEmpty,此时这样写: if (str?.isNotEmpty()) { // str is not empty, do something } ...

  9. Qt编写气体安全管理系统22-报警联动

    一.前言 报警联动功能不是一个常规的功能,一般是给客户定制的功能,比如探测器采集到的数据报警了,不仅本地要播放报警声音,存储报警记录,发送报警短信和邮件,还需要触发警号面板灯进行报警,而警号面板指示灯 ...

  10. 安卓 android studio 报错 All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com

    这个问题是Android studio升级到3.0之后,运行的时候会提示gradle要升级到3.5版本才能编译.于是我把我的gradle升级到了 gradle-4.1-milestone-1 版本,是 ...