原文:[url]http://oldrev.iteye.com/blog/105074[/url]
关键字: D2.0 D const final invariant constness
D 2.0 Const/Final/Invariant 概念简介
D 2.0 specs 里的相关文档可读性不佳,因此我总结了一个简单的 const/final/invariant 概念简介,更详细的用法还请参考 D 2.0 specs。
在2.0中,invariant 和 const 有作存储类、定义类型和定义成员函数三种用途,深刻地改变了D程序编写的方式,跟C++一样,使用const/final/invariant 需要更仔细地设计和编码,回报是提供了更好的类型安全性并能让编译器产生出更高效的代码。
这些 constness 特性,虽然看起来语法很复杂,但也比 C++ 的前后置 const 要容易理解记忆得多了,因为它不像 C++ 中的 const 定义那样存在很大的随意性。
1. invariant
1.1 invariant 作存储类(storage class)
存储类是一个指定数据存储地点或方式的标志,static 就是一种存储类,用来要求编译器把数据存储到程序的静态存储区中。
invariant 存储类定义一个真正的常量,这个常量决不能更改,甚至有可能是放在只读存储器中。因此,invariant 存储类定义的常量没有地址,编译器也会禁止任何的取地址行为。
invariant 定义的常量只能使用初始化语法赋予初始值,如果 invariant 为引用/指针类型,那么所引用的数据也同样是 invariant 的。
1.2 invariant 作类型
你可以用 invariant(TYPE) 的方法定义一个含有 invariant 属性的新类型,括号中的 TYPE 表示整个类型中适用于 invariant 的部分,比如: invariant(int)* ptr; 这行代码申明了一个指针变量 ptr,ptr本身是变量,但它所指向的类型 (int)是不可变的,因此 *ptr = 3; 这样的代码是一个语法错误。
1.3 invariant 成员函数
invariant 可以用于修饰类和结构的成员函数,在 invariant 成员函数中传入的 this 指针/引用及其关联的任何东西都保证为 invariant。invariant 成员函数只能访问该类或结构的invariant 成员变量或其他 invariant 成员函数。
2. const
2.1 const 存储类
const 存储类类似于 invariant 存储类,不同的是 const 定义的指针/引用所指向的数据可以是变量,因此它们可能会在其他地方被修改。
2.2 const 作类型
与 invariant 作类型类似,const(TYPE) 定义一个含有 const 属性的新类型。不同点是当 const(TYPE) 作为指针/引用类型时,其所指向的类型可以是变量,如:int a; const(int)* ptr = &a; ptr 本身是变量,ptr 也可以指向变量,但是通过 ptr 只能只读地访问 a。
2.3 const 成员函数
const 修饰的成员函数类似C++中函数声明后置的 const,表示他们不允许更改 "this" 指针/引用指向的对象数据。请注意这里的修辞,“不允许”意味着可以像C/C++一样用转型骗过编译器,不过欺骗编译器恐怕没什么好结果。与 invariant 成员函数类似,const 成员函数可以访问 invariant 和 const 成员变量和函数。
3. final 存储类
final 存储类定义一个数据的访问模式为只读,与 invariant 不同的是,编译器为 final 定义的对象在内存中分配了空间。换句话来说,final 对象跟真正的变量没什么区别,只是由编译器来强制实施对此对象的只读访问。final 定义的对象可以用初始化语法初始化或在构造函数中初始化(加入 final 对象是类成员的话,当然,模块的this()也支持)。
在成员函数方面,很早以前 final 已经用来表示禁止 override 了,final 也不能作为类型使用。
目前 D 2.0 只是 alpha 版,还有很多的 bugs,因此,如果出现了任何不符合上面理论的问题,请怪罪编译器及其作者,而不是我,谢谢合作。
关键字: D2.0 D const final invariant constness
D 2.0 Const/Final/Invariant 概念简介
D 2.0 specs 里的相关文档可读性不佳,因此我总结了一个简单的 const/final/invariant 概念简介,更详细的用法还请参考 D 2.0 specs。
在2.0中,invariant 和 const 有作存储类、定义类型和定义成员函数三种用途,深刻地改变了D程序编写的方式,跟C++一样,使用const/final/invariant 需要更仔细地设计和编码,回报是提供了更好的类型安全性并能让编译器产生出更高效的代码。
这些 constness 特性,虽然看起来语法很复杂,但也比 C++ 的前后置 const 要容易理解记忆得多了,因为它不像 C++ 中的 const 定义那样存在很大的随意性。
1. invariant
1.1 invariant 作存储类(storage class)
存储类是一个指定数据存储地点或方式的标志,static 就是一种存储类,用来要求编译器把数据存储到程序的静态存储区中。
invariant 存储类定义一个真正的常量,这个常量决不能更改,甚至有可能是放在只读存储器中。因此,invariant 存储类定义的常量没有地址,编译器也会禁止任何的取地址行为。
invariant 定义的常量只能使用初始化语法赋予初始值,如果 invariant 为引用/指针类型,那么所引用的数据也同样是 invariant 的。
1.2 invariant 作类型
你可以用 invariant(TYPE) 的方法定义一个含有 invariant 属性的新类型,括号中的 TYPE 表示整个类型中适用于 invariant 的部分,比如: invariant(int)* ptr; 这行代码申明了一个指针变量 ptr,ptr本身是变量,但它所指向的类型 (int)是不可变的,因此 *ptr = 3; 这样的代码是一个语法错误。
1.3 invariant 成员函数
invariant 可以用于修饰类和结构的成员函数,在 invariant 成员函数中传入的 this 指针/引用及其关联的任何东西都保证为 invariant。invariant 成员函数只能访问该类或结构的invariant 成员变量或其他 invariant 成员函数。
2. const
2.1 const 存储类
const 存储类类似于 invariant 存储类,不同的是 const 定义的指针/引用所指向的数据可以是变量,因此它们可能会在其他地方被修改。
2.2 const 作类型
与 invariant 作类型类似,const(TYPE) 定义一个含有 const 属性的新类型。不同点是当 const(TYPE) 作为指针/引用类型时,其所指向的类型可以是变量,如:int a; const(int)* ptr = &a; ptr 本身是变量,ptr 也可以指向变量,但是通过 ptr 只能只读地访问 a。
2.3 const 成员函数
const 修饰的成员函数类似C++中函数声明后置的 const,表示他们不允许更改 "this" 指针/引用指向的对象数据。请注意这里的修辞,“不允许”意味着可以像C/C++一样用转型骗过编译器,不过欺骗编译器恐怕没什么好结果。与 invariant 成员函数类似,const 成员函数可以访问 invariant 和 const 成员变量和函数。
3. final 存储类
final 存储类定义一个数据的访问模式为只读,与 invariant 不同的是,编译器为 final 定义的对象在内存中分配了空间。换句话来说,final 对象跟真正的变量没什么区别,只是由编译器来强制实施对此对象的只读访问。final 定义的对象可以用初始化语法初始化或在构造函数中初始化(加入 final 对象是类成员的话,当然,模块的this()也支持)。
在成员函数方面,很早以前 final 已经用来表示禁止 override 了,final 也不能作为类型使用。
目前 D 2.0 只是 alpha 版,还有很多的 bugs,因此,如果出现了任何不符合上面理论的问题,请怪罪编译器及其作者,而不是我,谢谢合作。