This page has been translated automatically.
编程
Fundamentals
Setting Up Development Environment
Usage Examples
UnigineScript
C++
C#
UUSL (Unified UNIGINE Shader Language)
File Formats
Rebuilding the Engine and Tools
GUI
Double Precision Coordinates
应用程序接口
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
CIGI Client Plugin
Rendering-Related Classes
注意! 这个版本的文档是过时的,因为它描述了一个较老的SDK版本!请切换到最新SDK版本的文档。
注意! 这个版本的文档描述了一个不再受支持的旧SDK版本!请升级到最新的SDK版本。

Scope. Namespaces

Scope(作用域)

Scope决定某种在程序中进行使用的标识符在程序中的可访问区域,这种标识符可以是一个变量,一种枚举类型,一种函数,一个类,一个命名空间等。

注意
对于变量,作用域决定了着其可访问性及生命期,而生命期并受当前作用域的限制(具体细节信息请参看下列内容)。

作用域范围的大小取决于声明标识符的地点。例如如果在某个类的顶端位置处声明了一个变量,那么此变量的作用域便是整个类中的所有方法所涉及的范围。但如果在某个方法中声明了一个变量,那么此变量的作用域范围仅限于此方法的作用域范围内。

使用一组花括号({}) 定义一个新的作用域。

例如:

源代码 (UnigineScript)
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

如果在所有模块的外部使用花括号封装并声明一个标识符,那么此标示符的作用域为全局范围。这就是说声明此标识符后可在程序中的任意位置处访问此标识符。

注意
如果某种函数并未类的成员并在所有模块外部进行声明,那么同样此函数的作用域为全局范围。
例如:
源代码 (UnigineScript)
// foo()方法的作用域为全局范围
int foo() { log.message("Function in the global scope\n"); }

class Foo {
    Foo (){}
    // foo() 方法的作用域仅限Foo类的范围
    int foo(){ log.message("Class member function\n"); }
};

如上所述,变量的生命期并不受当前范围的限制。换句话说即本地变量的生命期与全局变量的生命期相同(除非 另有 注明)。例如:

源代码 (UnigineScript)
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的变量生命期并不受foo()范围的限制。因此在第二次调用foo()时,先前调用得到的值会增加。用C++的话说就是,其与使用静态修饰符声明的变量相似。

如果要对变量local_var的局部生命期进行仿真,应以如下方式对此变量进行初始化:

源代码 (UnigineScript)
int foo() {
    int local_var = 0;
    local_var++;
    log.message("local_var: %d\n",local_var);
}

foo(); // local_var: 1
foo(); // local_var: 1

作用域解析运算符

作用域解析运算符::被用来指定运算符涉及的语境。也可使用此运算符来访问命名空间外的变量,类作用域外的函数或者处理某个标识符的作用域。使用此标识符来表述全局变量及类中的成员。

通过::为函数(变量,类,命名空间等)名增加一个前缀,指定使用全局范围的函数。这样可以确保范围解析将从全局范围开始而不从当前范围开始。例如:

源代码 (UnigineScript)
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库中函数为全局解析范围。

假设用户自定义类中某个函数的函数名与UnigineScript库中某个函数名相同。 要在用户自定义函数的作用域范围内调用原始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可对诸如类,对象及函数名称实体进行分组。全局作用域可被分成子作用域,每个子作用域具有其自己的名称。

命名空间的格式为:

源代码 (UnigineScript)
namespace identifier {
	// 实体
}

定义命名空间的示例:

源代码 (UnigineScript)
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

也可使用using关键字将命名空间的名称引入当前声明区域。

源代码 (UnigineScript)
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
最新更新: 2017-10-20
Build: ()