ASD Primer Ch1. C++语言基础
介绍
C++的创始人Bjarne Stroustrup说过:“C++是一门通用语言...它改进了C语言,使它支持了数据抽象,面向对象编程,以及泛型编程。”[Stroustrup 2000] 正是因为C++的这些特性,特别是支持面向对象编程的能力,在1994年,Symbian(Psion的一部分)采用了C++来重写它的16位操作系统SIBO,从而产生了EPOC32系统,也就是由它开始,进化成为了现在Symbian操作系统。
然而Symbian操作系统并没有完全采用C++,而是谨慎的放弃了诸如异常、模板以及STL(标准模板库)这样一些特性。并且Symbian还扩展了-更准确的说是为C++做了一些补充,例如严格的编码约定,小容量内存管理技术,以及专为移动电话优化了的算法等。在Symbian操作系统中用C++语言开发,要求开发者具有很强的主流C++语言的应用能力。
本章包括了ASD考试所要求的语言基础:类型、指令、函数以及对工具链的简单介绍。我们只在需要时会使用一些OO(面向对象)的语法,OO会在第二章和第三章详细介绍。
1.1 类型
本节将介绍基础类型,包括:指针、引用以及数组。下面会提及一些非常基础的概念,同样也会包含一些语法陷阱。我们不要求应试者能记住所有的语法细节,但是他不应该被这些不常见的语法所迷惑。
重要信息
定义
用C++语言来做任何实际的事情都需要用到变量和函数。定义一个变量需要给变量取一个名字、定义一种类型、以及规定一组可以对它进行的操作。
通俗的说,类型指明了这个名字所能包含什么样的值,以及什么样的操作对这些值是合法的。例如,整数类型只允许包含整数的值,并且限制了只有例如加减这样的操作可以关联上它们。
C++中定义的所有值都被保存在内存中。然而C++语言本身并没有定义这些值需要多少内存-而将这一点定义为“实现的细节”-但是一般来说,int类型需要32位字长(4字节)来表示。基本上可以表示成:
上面n是一个变量的名字,它是int类型,并且被初始化为值42(一般被保存在4个字节的内存区域中)。
基本类型
下面的这些为C++中的基本类型:
- bool - 布尔型
- char - 字符型
- int - 整型
- double - 浮点数型
还有一种w_char_t类型,表示的是宽字符型,没有例举在这里。
上面前三种类型:bool、char、int,均可被看作是整数类型,因为它们的值都不会包含小数部分。整数类型可以被转换到较大的类型而不损失任何精度,例如从char类型转换到int类型。而在整数类型和浮点数类型之间转换的话,精度则不能被保证。例如,从一个double类型转到int类型,其小数部分会被四舍五入到整数部分。
整数类型和浮点数类型被统称为算术类型,可以在它们身上进行算术运算。算术类型之间可以在赋值和表达式中被任意混用,但是这样做并不被推荐,因为这会导致未定义的行为和损失精度的风险。
可以使用signed(有符号型)、unsigned(无符号型)、short(短整型)、long(长整型)来更准确的控制整型的存储空间大小。例如unsigned类型(无符号性)释放了符号位,这样就能使用同样大小的存储空间来表达更大的正整数。而unsigned short char(无符号短字符类型)一边用来表示一个8位的ASCII字符。
Typedef(类型定义)
为了向开发者提供类型命名更大的灵活性,或者是为了方便程序移植,C++允许使用typedef来为类型定义别名。
除了在说起TUint32和unsigned long int,前者显得更简洁些,而且如果我们打算把程序移植到一个长整型(long)定义小于32位的系统上时,我们只需要修改typedef部分的代码来容纳一个更大的类型。
需要注意的是typedef并不是特殊的类型,而是原有类型的同义语或别名。因此TUint32并没有特别的方法或者类型检查机制,它仅仅是原有类型的一个替换而已。
常数和枚举类型
使用关键字const可以减少重新给某个常量赋值的错误。使用const修饰的常量只能在声明时被赋值,其后就不能再被重新赋值。
C++还支持一种传统方式来定义常量,那就是使用#define这个预处理指令(关于预处理专题,请参考1.6节)。
其实这是一种相当粗鲁的定义常量的方式,预处理器会在C++编译器执行之前使用42来替换掉所有的N。这会产生两方面的问题:一、这样的代码没有通过作用域检查,二、代码也没有通过类型检查。如果使用const来定义整型,N则只能被定义一次,清楚的被定义为整型,并且有一个明确的作用域。然而如果使用预处理器机制,则不会有作用域的限制,N在任何地方都可以被重复定义多次,被定义成任何类型和任何值。
C++支持的最后一种常数定义方式是使用用户自定义的枚举类型:
{
EPriorityIdle = -100,
EPriorityLow = -20,
EPriorityStandard = 0,
EPriorityUserInput = 10,
EPriorityHigh = 20
};
TPriority priority = EPriorityLow;
priority = EPriorityHigh; // (a) 允许:priority自身并不是常量
priority = -10; // (b) 不允许:-10不是TPriority类型
priority = TPriority(-10); // (c) 允许: -10在枚举类型的范围内,可以被显式的转换
priority = TPriority('a'); // (d) 允许!'a'是字符类型-整型的一种
int i = EPriorityIdle; // (e) 允许
在上面的例子中,TPriority是一种枚举类型的名字,它有五个被赋值了的常数枚举值。这不是必须的,因为如果没有赋值,第一个枚举值的值将会是0,而接下来的每个枚举值的值比前一个增加1。
enum类型的变量priority只能被赋值为类型是TPriority的常量,尽管整型也可以被赋值为TPriority类型的值,参见上面代码的注释。
第10章会叙述Symbian操作系统如何在DLL中处理const值。