Scope. Namespaces
ScopeScope(作用域)#
Scope决定某种在程序中进行使用的标识符在程序中的可访问区域,这种标识符可以是一个变量,一种枚举类型,一种函数,一个类,一个命名空间等。
作用域范围的大小取决于声明标识符的地点。例如如果在某个类的顶端位置处声明了一个变量,那么此变量的作用域便是整个类中的所有方法所涉及的范围。但如果在某个方法中声明了一个变量,那么此变量的作用域范围仅限于此方法的作用域范围内。
使用一组花括号({}) 定义一个新的作用域。
例如:
namespace Foo {
int a = 10;
}
int a = 5;
log.message("Foo::a is %d, a is %d", Foo::a,a);
Foo::a is 10, a is 5
如果在所有模块的外部使用花括号封装并声明一个标识符,那么此标示符的作用域为全局范围。这就是说声明此标识符后可在程序中的任意位置处访问此标识符。
// foo()方法的作用域为全局范围
int foo() { log.message("Function in the global scope\n"); }
class Foo {
Foo (){}
// foo() 方法的作用域仅限Foo类的范围
int foo(){ log.message("Class member function\n"); }
};
如上所述,变量的生命期并不受当前范围的限制。换句话说即本地变量的生命期与全局变量的生命期相同(除非 另有 注明)。例如:
int foo() {
int local_var;
local_var++;
log.message("local_var: %d\n",local_var);
}
foo(); // local_var: 1
foo(); // local_var: 2
如果要对变量local_var的局部生命期进行仿真,应以如下方式对此变量进行初始化:
int foo() {
int local_var = 0;
local_var++;
log.message("local_var: %d\n",local_var);
}
foo(); // local_var: 1
foo(); // local_var: 1
Scope Resolution Operator作用域解析运算符#
作用域解析运算符::被用来指定运算符涉及的语境。也可使用此运算符来访问命名空间外的变量,类作用域外的函数或者处理某个标识符的作用域。使用此标识符来表述全局变量及类中的成员。
通过::为函数(变量,类,命名空间等)名增加一个前缀,指定使用全局范围的函数。这样可以确保范围解析将从全局范围开始而不从当前范围开始。例如:
namespace Test {
int a;
void info() { log.message("a from the scope of the 1st namespace is %d\n",a); }
}
int init () {
namespace Test {
int a;
void info() { log.message("a from the scope of the 2nd namespace is %d\n",a); }
}
// 访问全局命名空间的成员
::Test::a = 10;
::Test::info();
// 访问在当前作用域内声明的命名空间成员
Test::a = 30;
Test::info();
return 1;
}
a from the scope of the 1st namespace is 10
a from the scope of the 2nd namespace is 30
假设用户自定义类中某个函数的函数名与UnigineScript库中某个函数名相同。 要在用户自定义函数的作用域范围内调用原始UnigineScript函数,将 :: 运算符作为函数的前缀添加到函数名称前。 例如:
class Foo {
Foo() {}
// 在Foo类解析范围内的用户自定义函数
void rotate(float angle) {
// UnigineScript函数用来获取按照所给角度围绕轴旋转的矩阵
mat4 rot = ::rotate(vec3(1.0f, 0.0f, 0.0f), angle);
}
};
NameSpace::getFunctionID(): can't find "rotate" function with 2 arguments
Namespaces命名空间#
Namespaces可对诸如类,对象及函数名称实体进行分组。全局作用域可被分成子作用域,每个子作用域具有其自己的名称。
命名空间的格式为:
namespace identifier {
// 实体
}
定义命名空间的示例:
namespace Foo {
int a = 10;
}
int a = 5;
log.message("Foo::a is %d, a is %d", Foo::a,a);
// 输出: Foo::a is 10, a is 5
namespace Foo::Bar {
int a = 10;
}
void foo() {
using Foo::Bar;
log.message("Foo::Bar::a is %d\n",a);
}
foo();
// 输出: Foo::Bar::a is 10