D语言 绝对简明手册 [2006-09-15 04:35:33]
Contents
作者:张沈鹏 Email:[email protected] 更新日期:2007-11-5 18:26 D语言版本:DMD0.109 参考文献: D程序设计语言 中文版(译者:uframer,qiezi,ideage)
1. typedef 重命名类型
typedef 可以指定一个不同于其底层类型(underlying type)的初始值:
typedef int myint = 7; myint m; // 初始化为 7
2. alias 别名
alias abc.Foo.bar myint;
2.1. 函数别名
import string; alias string.strlen mylen; int len = mylen("hello"); // 实际上调用的是 string.strlen()
2.2. 模板别名
template Foo2(T) { alias T t; } alias Foo2!(int) t1;
2.3. 别名解决异构问题
version (Win32) { alias win32.foo myfoo; } version (linux) { alias linux.bar myfoo; }
2.4. 别名实现重载
class A { int foo(int a) { return 1; } } class B : A { int foo( int a, uint b ) { return 2; } } class C : B { int foo( int a ) { return 3; } alias B.foo foo; }
3. 所见即所得字符串
- r" 多个所见即所得字符 "
或
多个所见即所得字符
4. ‘_’来格式化数字
123_456.567_8 // 123456.5678
5. 复数
4.5 + 6.2i
6. __XXX__ 特殊记号
这些特殊的记号将按下表进行替换:
FILE 包含记号的源文件名
LINE 源文件中 记号所在行
DATE 编辑的日期 "mmm dd yyyy"
TIME 编辑的时间 "hh:mm:ss"
TIMESTAMP 编辑的时间和日期 "www mmm dd hh:mm:ss yyyy"
7. 前导的‘.’
意味着在全局级别查找名称。
8. 函数指针
int function(int) fp; // fp 是指向函数的指针 C 风格的声明函数指针的语法也被支持: int (*fp)(int); // fp 是指向函数的指针
9. 委托
是两块数据的聚集:一个对象的引用和一个函数指针。
当调用函数时,对象引用构造 this 指针。
委托不能用静态成员函数或者非成员函数初始化。
int delegate(int) dg; // dg 是函数的委托 class OB{ int member(int); } OB o; dg = &o.member; // dg 是 object o 的成员函数,member 的委托 dg(3); // 调用 o.member(3)
10. 类型的属性
10.1. 所有类型的属性
.init 初始值 .init 产生一个常量表达式,其值为默认初始值。如果应用到某个类型,其值为该类型的默认初始值。如果应用到某个变量或域,其值为这个变量或域的默认初始值。例如:
- typedef int t = 2; t c; int.init // is 0 c.init // is 2 t.init // is 2
.sizeof 以字节为单位的大小(等价于 C 的 sizeof(type)) .alignof 对齐大小 .mangleof string representing the 'mangled' representation of the type
10.2. 整数类型的属性
.init 初始值(0) .max 最大值 .min 最小值
10.3. 浮点的主要属性
- init 初始值 (NaN)
.infinity 无穷 .nan NaN 值 .dig 换算为十进制表示后的精度 .mant_dig 尾数的位数(bit) .max 可表示的最大值(除了无穷) .min 可表示的最小值(除了 0 )
10.4. 自定义属性
struct Foo { int data() { return m_data; } // 读属性 int data(int value) { return m_data = value; } // 写属性 private: int m_data; }
用法:
Foo f; f.data = 3; // 等价于 f.data(3); return f.data + 3; // 等价于 return f.data() + 3;
11. 废弃特征
我们经常会将库中的某一特征标记为废弃,同时仍然保留它以保持向后兼容。
这类声明可以被标记为废弃,这意味着可以通过设置编译器选项,在遇到引用这类声明的代码时产生错误:
deprecated { void oldFoo(); }
12. 访问权限(private等)
private、 package、 protected、 public 和 export 。
private 意味着只有本类内的及本类所在模块内的成员可以访问被保护的成员。私有成员不能被重写。私有模块成员等价于 C 程序中的 static 声明。
package 扩展了 private 的访问权,这样包中的成员就可以访问位于同一包内的其他的模块内的成员。如果包是嵌套的话,这条规则只应用于最内层的包。
protected 意味着只有本类内或者派生类内的成员或者本类所在模块内的成员可以访问被保护的成员。protected 不能用于模块成员。
public 意味着可执行程序中的任何代码都可以访问这个成员。
export 意味着可执行程序外的任何代码都可以访问这个成员。export 的意思也就是从 DLL 中导出定义。
== const 编译时估值的常量 ===
const int foo = 7; const { double bar = foo + 6; }
13. override 虚函数
必须用具有同基类中相同的名字和参数覆盖这个函数。
class Foo { int bar(); int abc(int x); } class Foo2 : Foo { override { int bar(char c); // 错误,Foo 中没有 bar(char) int abc(int x); // ok } }
14. static 静态类型
没有 this 引用。
静态函数决不会是虚的。
在整个程序中,静态数据只有一个实例。
15. auto 特征用于局部变量和类声明
auto 不能被用于全局的、静态的数据成员或者用 inout 或 out 修饰的参数。
auto 的数组是非法的,函数返回值也不允许是 auto 的。
如果不是初始化的话,是不允许对 auto 赋值的。
import std.stdio; import std.file; int main() { auto hi="good day"; writef("%s",hi); getchar(); return 0; }
16. 预定义 Pragma
msg 在编译时打印出消息,赋值表达式 必须是字符串文字量:
pragma(msg, "compiling...");
lib 指示编译对象文件时要链接的库。赋值表达式必须是字符串文字量:
pragma(lib,”foo.lib”);
17. cast用来转型
如果想要检测一个对象 o 是否是类 B 的一个实例,可以使用转型:
if (cast(B) o){// 如果 a 不是 B 类型,就返回 null // o 是 B 的一个实例 } else{ // o 不是 B 的一个实例 }
18. 切片表达式
后缀表达式 [ 赋值表达式 .. 赋值表达式 ]
如果 后缀表达式 的类型为静态或者动态数组,会隐式地声明变量 length ,并将数组的长度赋给它。
赋值表达式 有自己独立的声明作用域,length 和 赋值表达式 只出现在这个作用域中。
比如:
char[] id="good day"; writef("%s",id[length-3..length]);
19. null 空指针
从技术上说,它的类型是 (void *) 。
它可以被隐式地转换为任何指针类型。整数 0 不能被转换为空指针。null 也用于空数组。
20. 字符文字量
单个的字符,类型是 char、 wchar 或者 dchar 。
如果文字量是 \u 转义序列,类型就是 wchar 。
如果文字量是 \U 转义序列,类型就是 dchar 。
否则,它的类型是能够容纳它的最小的类型。
21. 短/无名函数
fp = function int(char c) { return 6;} ;
delegate int(long c) { return 6 + b; };
可以作为无名函数用于参数
delegate可以访问外围变量
22. assert 断言
assert ( Expression )
断言会计算 表达式 。
如果结果为假,会抛出一个 AssertError 异常。
如果结果为真,不会抛出任何异常。
如果 表达式 包含程序所依赖的任何副作用,就是一个错误。
通过编译时的命令行选项,编译器可以根本不对断言表达式求值。
断言表达式的返回 void 。
23. in 检测元素是否在关联数组中
int foo[char[]]; …… if ("hello" in foo)
24. new / delete
New 表达式用来在垃圾收集堆(默认情况)上或使用类指定的分配器分配内存。
在为多维数组分配内存时,声明按照同读取后缀数组声明顺序相同的顺序读取声明。
char[][] foo; // 字符串动态数组 foo = new char[][30]; // 分配 30 个字符串数组
指针,动态数组,或者参考在执行delete函数后将被设置为null
25. typeof(?) 返回?的类型
typeof(this) x; //当前类的类型
typeof(super) y //当前类的基类类型
26. typeid ( Type )
返回 类型 对应的 TypeInfo 类的实例。 如:
char[] hi="good"; writef( "%s", typeid( typeof(hi) ) );
输出:
char[]
27. is 类型判断
内置类型判别符号
typedef struct union class interface enum function delegate
27.1. is ( Type )
判断是否是一种类型
alias int func(int); void foo(){ if ( is(func[]) ) //不成立,应用函数指针不可以作为数组 printf("satisfied\n"); else printf("not satisfied\n"); if (is([][])) // error, [][] is not a syntactically valid type }
27.2. is(A:B)
类型A是否是类型B,或是否可以隐式转换为类型B
比如:
is(short:int)//返回1
27.3. is(A==B)
判断类型A是否是类型B
alias short bar; typedef char foo; void foo(bar x) { if ( is(bar == int) )//不满足,short不是int printf("satisfied\n"); else printf("not satisfied\n"); if ( is(foo == typedef) ) //满足,因为是typedef printf("satisfied\n"); else printf("not satisfied\n"); }
其上 is(bar:short)和is(bar:short)均返回1
is(foo:char) //返回1
is(char:foo) //返回0
27.4. is(A B)
和static if配合使用,如:
static if ( is(bar[] T) ) alias T S;//如果bar[]是一种类型 else alias long[] S;
27.5. is(A B:C)
static if ( is(abc U[] : U*) )//如果abc可以表示为U*,则用U表示U[]类型 U u;
28. 作用域
同一个域中一个变量只能声明一次 语句块为局部符号引入了新的作用域。尽管如此,在函数内部,局部符号的名称必须唯一。
void func2() { int x; { int x; // 非法,x 在函数作用域内定义了多次 } } void func4() { { int x; } { x++; // 非法,x 未定义 } }
29. foreach
29.1. 数组
char[] a="good"; //i为索引 foreach (int i, char c; a) { printf("a[%d] = '%c'\n", i, c); } foreach (char c; a) { printf("%c",c); }
29.2. 关联数组
如果作用于关联数组,可以声明一个或者两个变量。 如果声明了一个变量,那么这个变量就被赋予数组元素的值 ,元素的顺序是未定义的
double[char[]] b; // 索引 类型是 char[],值 类型是 double b["good"]=1.1; b["yes"]=2; foreach (double d; b) { printf("%g\n", d); } foreach (char[] s, double d; b) { printf("b['%.*s'] = %g\n", s, d); }
29.3. 自定义类型
如果聚集是一个结构或者类对象,则它必须定义具有如下类型的 opApply 函数:
- int opApply(int delegate(inout Type [, ...]) dg);
未完....