阅读Android源码须要对C++基础语法有必定的认识,借此对C++作一个简单的语法认知。html
一、数据类型前端
类型 | 关键字 |
---|---|
布尔型 | bool |
字符型 | char |
整型 | int |
浮点型 | float |
双浮点型 | double |
无类型 | void |
宽字符型 | wchar_t |
一些基本类型可使用一个或多个类型修饰符进行修饰:ios
(1)typedef 声明编程
使用 typedef 为一个已有的类型取一个新的名字。下面是使用 typedef 定义一个新类型的语法:typedef type newname;数组
(2)枚举类型安全
枚举类型(enumeration)是C++中的一种派生数据类型,它是由用户定义的若干枚举常量的集合。数据结构
若是一个变量只有几种可能的值,能够定义为枚举(enumeration)类型。所谓"枚举"是指将变量的值一一列举出来,变量的值只能在列举出来的值的范围内。编程语言
建立枚举,须要使用关键字 enum。枚举类型的通常形式为:ide
enum 枚举名{ 标识符[=整型常数], 标识符[=整型常数], ... 标识符[=整型常数] } 枚举变量;
若是枚举没有初始化, 即省掉"=整型常数"时, 则从第一个标识符开始。函数
默认状况下,第一个名称的值为 0,第二个名称的值为 1,第三个名称的值为 2,以此类推。可是,您也能够给名称赋予一个特殊的值,只须要添加一个初始值便可。例如,在下面的枚举中,green 的值为 5。
enum color { red, green=5, blue };
在这里,blue 的值为 6,由于默认状况下,每一个名称都会比它前面一个名称大 1,但 red 的值依然为 0。
(3)变量类型
变量的名称能够由字母、数字和下划线字符组成。它必须以字母或下划线开头。
几种基本变量类型:bool、char、int、float、double、void、wchar_t
C++ 也容许定义各类其余类型的变量,好比枚举、指针、数组、引用、数据结构、类等等。
例如,列出几个有效的声明:
int i, j, k; char c, ch; float f, salary; double d;
extern int d = 3, f = 5; // d 和 f 的声明
int d = 3, f = 5; // 定义并初始化 d 和 f
byte z = 22; // 定义并初始化 z
char x = 'x'; // 变量 x 的值为 'x'
(4)左值(Lvalues)和右值(Rvalues)
C++ 中有两种类型的表达式:
变量是左值,所以能够出如今赋值号的左边。数值型的字面值是右值,所以不能被赋值,不能出如今赋值号的左边。
(5)变量做用域
做用域是程序的一个区域,通常来讲有三个地方能够定义变量:
在函数或一个代码块内部声明的变量,称为局部变量。
在函数参数的定义中声明的变量,称为形式参数。
在全部函数外部声明的变量,称为全局变量。
(6)常量
常量是固定值,在程序执行期间不会改变。这些固定的值,又叫作字面量。
常量能够是任何的基本数据类型,可分为整型数字、浮点数字、字符、字符串和布尔值。
整数常量能够是十进制、八进制或十六进制的常量。
浮点常量由整数部分、小数点、小数部分和指数部分组成。可使用小数形式或者指数形式来表示浮点常量。
当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含二者。当使用指数形式表示时, 必须包含小数点、指数,或同时包含二者。带符号的指数是用 e 或 E 引入的。
例如:
3.14159 // 合法的 314159E-5L // 合法的 510E // 非法的:不完整的指数 210f // 非法的:没有小数或指数 .e55 // 非法的:缺乏整数或分数
布尔常量共有两个,它们都是标准的 C++ 关键字:
字符常量是括在单引号中。若是常量以 L(仅当大写时)开头,则表示它是一个宽字符常量(例如 L'x'),此时它必须存储在 wchar_t 类型的变量中。不然,它就是一个窄字符常量(例如 'x'),此时它能够存储在 char 类型的简单变量中。
字符常量能够是一个普通的字符(例如 'x')、一个转义序列(例如 '\t'),或一个通用的字符(例如 '\u02C0')。
在 C++ 中,有一些特定的字符(转义序列码),当它们前面有反斜杠时,它们就具备特殊的含义,被用来表示如换行符(\n)或制表符(\t)等。
字符串字面值或常量是括在双引号 "" 中的。一个字符串包含相似于字符常量的字符:普通的字符、转义序列和通用的字符。
定义常量:在 C++ 中,有两种简单的定义常量的方式:
(7)修饰符类型
C++ 容许在 char、int 和 double 数据类型前放置修饰符。修饰符用于改变基本类型的含义,因此它更能知足各类情境的需求。
下面列出了数据类型修饰符:
修饰符 signed、unsigned、long 和 short 可应用于整型,signed 和 unsigned 可应用于字符型,long 可应用于双精度型。
修饰符 signed 和 unsigned 也能够做为 long 或 short 修饰符的前缀。例如:unsigned long int。
C++ 容许使用速记符号来声明无符号短整数或无符号长整数。您能够不写 int,只写单词 unsigned、short 或 unsigned、long,int 是隐含的。例如:
unsigned x; unsigned int y;
(8)类型限定符
提供了变量的额外信息:
const | const 类型的对象在程序执行期间不能被修改改变。 |
volatile | 修饰符 volatile 告诉编译器不须要优化volatile声明的变量,让程序能够直接从内存中读取变量。对于通常的变量编译器会对变量进行优化,将内存中的变量值放在寄存器中以加快读写效率。 |
restrict | 由 restrict 修饰的指针是惟一一种访问它所指向的对象的方式。只有 C99 增长了新的类型限定符 restrict。 |
(9)C++ 存储类
存储类定义 C++ 程序中变量/函数的范围(可见性)和生命周期。这些说明符放置在它们所修饰的类型以前。下面列出 C++ 程序中可用的存储类:
指示编译器在程序的生命周期内保持局部变量的存在,而不须要在每次它进入和离开做用域时进行建立和销毁。所以,使用 static 修饰局部变量能够在函数调用之间保持局部变量的值。
static 修饰符也能够应用于全局变量。当 static 修饰全局变量时,会使变量的做用域限制在声明它的文件内。
用于提供一个全局变量的引用,全局变量对全部的程序文件都是可见的。当您使用 'extern' 时,对于没法初始化的变量,会把变量名指向一个以前定义过的存储位置。
当您有多个文件且定义了一个能够在其余文件中使用的全局变量或函数时,能够在其余文件中使用 extern 来获得已定义的变量或函数的引用。能够这么理解,extern 是用来在另外一个文件中声明一个全局变量或函数。
extern 修饰符一般用于当有两个或多个文件共享相同的全局变量或函数的时候。
使用 thread_local 说明符声明的变量仅可在它在其上建立的线程上访问。 变量在建立线程时建立,并在销毁线程时销毁。 每一个线程都有其本身的变量副本。
thread_local 说明符能够与 static 或 extern 合并。
能够将 thread_local 仅应用于数据声明和定义,thread_local 不能用于函数声明或定义。例如:
thread_local int x; // 命名空间下的全局变量 class X { static thread_local std::string s; // 类的static成员变量 }; static thread_local std::string X::s; // X::s 是须要定义的 void foo() { thread_local std::vector<int> v; // 本地变量 }
(10)运算符
下类型的运算符:
运算符 | 描述 |
---|---|
sizeof | sizeof 运算符返回变量的大小。例如,sizeof(a) 将返回 4,其中 a 是整数。 |
Condition ? X : Y | 条件运算符。若是 Condition 为真 ? 则值为 X : 不然值为 Y。 |
, | 逗号运算符会顺序执行一系列运算。整个逗号表达式的值是以逗号分隔的列表中的最后一个表达式的值。 |
.(点)和 ->(箭头) | 成员运算符用于引用类、结构和共用体的成员。 |
Cast | 强制转换运算符把一种数据类型转换为另外一种数据类型。例如,int(2.2000) 将返回 2。 |
& | 指针运算符 & 返回变量的地址。例如 &a; 将给出变量的实际地址。 |
* | 指针运算符 * 指向一个变量。例如,*var; 将指向变量 var。 |
二、基本语法
(1)循环
循环类型 | 描述 |
---|---|
while 循环 | 当给定条件为真时,重复语句或语句组。它会在执行循环主体以前测试条件。 |
for 循环 | 屡次执行一个语句序列,简化管理循环变量的代码。 |
do...while 循环 | 除了它是在循环主体结尾测试条件外,其余与 while 语句相似。 |
嵌套循环 | 您能够在 while、for 或 do..while 循环内使用一个或多个循环。 |
(2)判断
语句 | 描述 |
---|---|
if 语句 | 一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。 |
if...else 语句 | 一个 if 语句 后可跟一个可选的 else 语句,else 语句在布尔表达式为假时执行。 |
嵌套 if 语句 | 您能够在一个 if 或 else if 语句内使用另外一个 if 或 else if 语句。 |
switch 语句 | 一个 switch 语句容许测试一个变量等于多个值时的状况。 |
嵌套 switch 语句 | 您能够在一个 switch 语句内使用另外一个 switch 语句。 |
(3)函数
一个函数的组成部分:
若是函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。
形式参数就像函数内的其余局部变量,在进入函数时被建立,退出函数时被销毁。
当调用函数时,向函数传递参数的方式:
调用类型 | 描述 |
---|---|
传值调用 | 该方法把参数的实际值复制给函数的形式参数。在这种状况下,修改函数内的形式参数对实际参数没有影响。 |
指针调用 | 该方法把参数的地址复制给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
引用调用 | 该方法把参数的引用复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
(4)数组
能够存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它每每被认为是一系列相同类型的变量。
全部的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。
例如:double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
(5*)指针
每个变量都有一个内存位置,每个内存位置都定义了可以使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。
指针是一个变量,其值为另外一个变量的地址,即,内存位置的直接地址。就像其余变量或常量同样,您必须在使用指针存储其余变量地址以前,对其进行声明。指针变量声明的通常形式为:
type *var-name;
(type 是指针的基类型,var-name 是指针变量的名称。星号是用来指定一个变量是指针。)
例如:
int *ip; /* 一个整型的指针 */ double *dp; /* 一个 double 型的指针 */ float *fp; /* 一个浮点型的指针 */ char *ch; /* 一个字符型的指针 */
使用指针时会频繁进行如下几个操做:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值。
例如:
#include <iostream> using namespace std; int main () { int var = 20; // 实际变量的声明 int *ip; // 指针变量的声明 ip = &var; // 在指针变量中存储 var 的地址 cout << "Value of var variable: "; cout << var << endl; //20 // 输出在指针变量中存储的地址 cout << "Address stored in ip variable: "; cout << ip << endl; //地址 // 访问指针中地址的值 cout << "Value of *ip variable: "; cout << *ip << endl; //20 return 0; }
(6)引用&
引用变量是一个别名,也就是说,它是某个已存在变量的另外一个名字。一旦把引用初始化为某个变量,就可使用该引用名称或变量名称来指向变量。
例如:
int i = 17; int& r = i; //为 i 声明引用变量 double& s = d;
(7)结构
定义结构,必须使用 struct 语句。struct 语句定义了一个包含多个成员的新的数据类型。
例如:
#include <iostream> #include <cstring> using namespace std; // 声明一个结构体类型 Books struct Books { char title[50]; char author[50]; char subject[100]; int book_id; }; int main( ) { Books Book1; // 定义结构体类型 Books 的变量 Book1 Books Book2; // 定义结构体类型 Books 的变量 Book2 // Book1 详述 strcpy( Book1.title, "C++ 教程"); strcpy( Book1.author, "Runoob"); strcpy( Book1.subject, "编程语言"); Book1.book_id = 12345; // Book2 详述 strcpy( Book2.title, "CSS 教程"); strcpy( Book2.author, "Runoob"); strcpy( Book2.subject, "前端技术"); Book2.book_id = 12346; // 输出 Book1 信息 cout << "第一本书标题 : " << Book1.title <<endl; // 输出 Book2 信息 cout << "第二本书标题 : " << Book2.title <<endl; return 0; }
能够定义指向结构的指针,方式与定义指向其余类型变量的指针类似,以下所示:
struct Books *struct_pointer;
如今,您能够在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址,请把 & 运算符放在结构名称的前面,以下所示:
struct_pointer = &Book1;
为了使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符,以下所示:
struct_pointer->title;
注:可使用typedf为结构体定义别名
三、面向对象
(1)继承
格式:
class derived-class: access-specifier base-class
其中,访问修饰符 access-specifier 是 public、protected 或 private 其中的一个,base-class 是以前定义过的某个类的名称。若是未使用访问修饰符 access-specifier,则默认为 private。
派生类能够访问基类中全部的非私有成员。所以基类成员若是不想被派生类的成员函数访问,则应在基类中声明为 private。
一个派生类继承了全部的基类方法,但下列状况除外:
多继承即一个子类能够有多个父类,它继承了多个父类的特性。
C++ 类能够从多个类继承成员,语法以下:
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,… { <派生类类体> };
(2)函数重载
在同一个做用域内,能够声明几个功能相似的同名函数,可是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不一样。您不能仅经过返回类型的不一样来重载函数。
(3)多态
当类之间存在层次结构,而且类之间是经过继承关联时,就会用到多态。
C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不一样的函数。
#include <iostream> using namespace std; class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } virtual int area() { cout << "Parent class area :" <<endl; return 0; } }; class Rectangle: public Shape{ public: Rectangle( int a=0, int b=0):Shape(a, b) { } int area () { cout << "Rectangle class area :" <<endl; return (width * height); } }; class Triangle: public Shape{ public: Triangle( int a=0, int b=0):Shape(a, b) { } int area () { cout << "Triangle class area :" <<endl; return (width * height / 2); } }; // 程序的主函数 int main( ) { Shape *shape; Rectangle rec(10,7); Triangle tri(10,5); // 存储矩形的地址 shape = &rec; // 调用矩形的求面积函数 area shape->area(); // 存储三角形的地址 shape = &tri; // 调用三角形的求面积函数 area shape->area(); return 0; }
虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中从新定义基类中定义的虚函数时,会告诉编译器不要静态连接到该函数。
咱们想要的是在程序中任意点能够根据所调用的对象类型来选择调用的函数,这种操做被称为动态连接,或后期绑定。
想要在基类中定义虚函数,以便在派生类中从新定义该函数更好地适用于对象,可是在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数。
例如:
class Shape { protected: int width, height; public: Shape( int a=0, int b=0) { width = a; height = b; } // pure virtual function virtual int area() = 0; };
= 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数。
(4)数据抽象
只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节。
(5)数据封装
封装是面向对象编程中的把数据和操做数据的函数绑定在一块儿的一个概念,这样能避免受到外界的干扰和误用,从而确保了安全。数据封装引伸出了另外一个重要的 OOP 概念,即数据隐藏。
数据封装是一种把数据和操做数据的函数捆绑在一块儿的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
C++ 经过建立类来支持封装和数据隐藏(public、protected、private)。
例如:
class Box { public: double getVolume(void) { return length * breadth * height; } private: double length; // 长度 double breadth; // 宽度 double height; // 高度 };
(6)接口(抽象类)
接口描述了类的行为和功能,而不须要完成类的特定实现。
C++ 接口是使用抽象类来实现的,抽象类与数据抽象互不混淆,数据抽象是一个把实现细节与相关的数据分离开的概念。
若是类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。纯虚函数是经过在声明中使用 "= 0" 来指定的。
设计抽象类(一般称为 ABC)的目的,是为了给其余类提供一个能够继承的适当的基类。抽象类不能被用于实例化对象,它只能做为接口使用。
所以,若是一个 ABC 的子类须要被实例化,则必须实现每一个虚函数,这也意味着 C++ 支持使用 ABC 声明接口。若是没有在派生类中重载纯虚函数,就尝试实例化该类的对象,会致使编译错误。
可用于实例化对象的类被称为具体类。