【作用域】外部变量、外部函数与作用域

在学习C++过程中,经常看到这么一个说法:“命名空间作用域下的....”,其实C++的作用域(以前一直都是认为只是参数的有效范围)一直都在用,但系统的划分可能却没划分过,因此,将C++的作用域划分记录在此。

1.作用域

所谓作用域,即一个标志符在程序中起作用的区域。在C++中,作用域被细致的划分为函数原型作用域、局部作用域、类作用域、命名空间作用域

1.1函数原型作用域

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

例如,有如下函数声明:

 double area (double radius);

标识符radius的作用(或称有效)范围就在函数area形参列表的左右括号之间,在程序的其他地方不能引用这个标识符。因此标识符radius的作用域称做函数原型作用域。

1.2局部作用域

所谓局部作用域,是指在某一局部内生效。如下图:

局部作用域示意图

 如上所示,在函数fun的形参列表中声明了形参a,在函数体内声明了变量b,并用a的值初始化b,接下来在if语句内声明了c。在这里,a,b,c都是具有局部作用域,其作用域从声明处开始,一直到声明所在的块结束的大括号为止,具有局部作用域的变量也称为局部变量。

1.3类作用域

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

1.如果在类X的成员函数中没有声明同名的局部作用域标识符,那么在该函数内可以直接访问成员m。如果声明了,则局部作用域标识符会优于成员m的标识符。

2.通过表达式:(类X实例化对象)x.mX::m,第一种是通过对象访问数据成员,第二种是m为类X的静态数据成员访问方式。需要注意的是:如果类的对象在类外部是不能直接访问私有数据成员的,只能通过成员函数访问,但是,如果是在类内部是可以访问的。如以下代码是合法的:

template <class T>
class MyClass
{
 private:
    T value;
 public:
    void assign(const MyClass<T>& x)
    {
        value=x.value;
    }
    ......
};

 3.通过ptr->m这样的表达式,其中ptr为指向类X的一个对象的指针。

1.4命名空间作用域

凡是在命名空间namespace name{}之内定义的,且不属于上述各个作用域的,都属于是命名空间作用域

我们常常在代码中命名一些全局变量。也经常说他是写在了命名空间内,但是也没见我们用namespace 名字{}把他包含在内啊?这是怎么回事呢?在这里就要说两个特殊的命名空间作用域:

1.4.1全局命名空间:

全局命名空间是默认的默认命名空间,在显示声明的命名空间之外的声明都是默认声明到了一个全局命名空间中了,这也就解释了我们为什么经常没写namespace却也说某个变量是定义在了命名空间内的原因。

1.4.2匿名命名空间:

匿名命名空间是没有name名字的命名空间,其作用是在以下的外部变量和函数中说明。

2.外部变量和外部函数

外部变量和外部函数是指不仅可以在定义它的源文件内使用,还允许其在其他文件中使用。

需要指出的1:在命名空间作用域中的变量和函数,默认都是外部的。其他文件想要使用外部变量或者外部函数,只需要加上关键字extern声明下即可。

需要指出的2:外部变量和函数可以有多处声明,但是其定义性的声明只能是唯一的,即不允许重复定义。

从上面所示,我们得知,全局命名空间作用域中的变量和函数,默认情况下也是外部的,比如我们在一个主函数文件中定义了一个全局变量,全局函数,虽然我们没有将其定义在namespace name{},但因其是在默认的全局命名空间作用域内也是一种命名空间作用域,故其默认是允许其他cpp文件声明后使用的。

既然是默认允许其他文件使用,但如果我只想在我本文件内使用不想被其他文件使用呢?这种情况还是存在的,比如出于安全性考虑,我们不希望将一个我们确信只会在本文件内使用的内部变量或函数暴露给其他文件,或者在默认命名空间下的文件声明的一些函数和变量怕被其他文件调用后重名,这时候我们就想要将这些变量和函数限定在本文件内,就可以采用匿名命名空间的方式。

如1.4.2所示,匿名命名空间是指没有name的命名空间,其定义形式如下:

namespace

{

     //此处定义的一些函数和变量便不会被外部访问

}

posted @ 2020-07-23 18:44  小宋和小宋子  阅读(371)  评论(0)    收藏  举报