一、基础数据类型与变量
-
基本数据类型:
- 整型:
int
(通常占 4 字节,范围依赖于编译器和系统,一般为 -2147483648 到 2147483647)、short
(一般 2 字节)、long
(在 32 位系统通常 4 字节,64 位系统可能 8 字节)、long long
(一般 8 字节),用于表示整数。 - 浮点型:
float
(单精度,4 字节,有效数字约 6 - 7 位)、double
(双精度,8 字节,有效数字约 15 - 16 位),用于表示小数。 - 字符型:
char
(1 字节,用于存储单个字符,如字母、数字、标点等)。 - 布尔型:
bool
(1 字节,取值为true
或false
)。
- 整型:
-
变量定义与初始化:
- 定义格式:
数据类型 变量名;
,例如int num;
。 - 初始化:可以在定义时赋初值,如
int count = 0;
,也可以先定义后赋值,如int age; age = 20;
。
- 定义格式:
二、运算符与表达式
-
算术运算符 :
+
(加法)、-
(减法)、*
(乘法)、/
(除法,整数相除结果取整)、%
(取余,用于整数运算)。 -
关系运算符:
==
(等于)、!=
(不等于)、<
(小于)、>
(大于)、<=
(小于等于)、>=
(大于等于),用于比较两个值,结果为bool
类型。 - 逻辑运算符:
&&
(逻辑与,全真为真)、||
(逻辑或,有真为真)、!
(逻辑非,取反),用于操作bool
类型的值。 - 赋值运算符:
=
为基本赋值运算符,还有复合赋值运算符如+=
、-=
、*=
、/=
、%=
等,例如a += 5
等价于a = a + 5
。 - 其他运算符:
++
(自增运算符)、--
(自减运算符)、sizeof
(获取数据类型或变量所占字节数)、.
(成员访问运算符,用于访问结构体或类的成员)、->
(指向结构体或类成员的指针运算符)等。
三、控制结构
- 顺序结构:程序按照语句的书写顺序依次执行,是最基本的执行流程。
- 选择结构:
- if 语句:
if (条件表达式) { 语句块; }
,如果条件表达式为真,则执行语句块;还可以有if-else
结构,用于在条件为真和假时分别执行不同的语句块;以及if-else if-else
多重判断结构,用于处理多个分支情况。 - switch 语句:
switch (表达式) { case 常量表达式 1: 语句块 1; break; case 常量表达式 2: 语句块 2; break;... default: 语句块 n; }
,根据表达式的值与各个case
后的常量表达式匹配,执行相应的语句块,如果都不匹配则执行default
中的语句块,break
用于跳出switch
结构,防止执行后续的case
语句。
- if 语句:
- 循环结构:
- while 循环:
while (条件表达式) { 语句块; }
,只要条件表达式为真,就会重复执行语句块。 - do-while 循环:
do { 语句块; } while (条件表达式);
,先执行一次语句块,然后再判断条件表达式,若为真则继续循环,保证语句块至少执行一次。 - for 循环:
for (初始化表达式; 条件表达式; 更新表达式) { 语句块; }
,常用于已知循环次数的情况,初始化表达式在循环开始前执行一次,条件表达式用于判断是否继续循环,更新表达式在每次循环结束后执行,用于更新循环变量。
- while 循环:
四、数组与指针
- 数组:
- 定义:
数据类型 数组名[数组大小];
,例如int arr[10];
定义了一个包含 10 个int
类型元素的数组。 - 访问:通过下标访问数组元素,下标从 0 开始,如
arr[0]
、arr[1]
等;数组名本身是一个常量指针,指向数组的首地址。 - 多维数组:例如二维数组
int matrix[3][4];
,可以看作是一个包含 3 个一维数组(每个一维数组有 4 个元素)的数组,访问元素时使用matrix[i][j]
的形式,其中i
表示行下标,j
表示列下标。
- 定义:
- 指针:
- 定义:
数据类型 *指针变量名;
,例如int *p;
定义了一个指向int
类型数据的指针变量。 - 指针运算:指针可以进行算术运算,如
p++
(指针向后移动一个数据类型的字节数)、p--
(指针向前移动一个数据类型的字节数)、p + n
(指针向后移动n
个数据类型的字节数)、p - n
(指针向前移动n
个数据类型的字节数);还可以通过指针解引用*p
来访问其所指向的变量。 - 指针与数组的关系:数组名可以看作是指向数组首元素的指针,因此可以用指针来操作数组,例如
*(arr + i)
等价于arr[i]
,其中arr
是数组名,i
是下标。 - 指针作为函数参数:可以传递指针给函数,使函数能够修改外部变量的值,或者在函数内部操作较大的数据结构而避免数据的复制,提高效率;同时,也需要注意指针的有效性和避免悬空指针(指向已释放内存的指针)和野指针(未初始化的指针)的出现。
- 定义:
五、函数
- 函数定义:
- 一般形式:
返回值类型 函数名(参数列表) { 函数体; return 返回值; }
,例如int add(int a, int b) { return a + b; }
定义了一个名为add
的函数,接受两个int
类型的参数,返回它们的和。 - 函数重载:在同一作用域内,可以定义多个同名函数,只要它们的参数列表不同(参数个数、参数类型或参数顺序不同),编译器会根据调用时传递的实际参数来选择合适的函数版本进行调用。
- 一般形式:
- 函数调用:通过函数名和实参列表来调用函数,实参的值会传递给形参,函数执行完后,如果有返回值,则返回相应的值给调用者;函数调用可以出现在表达式中,也可以作为独立的语句。
- 函数参数传递:
- 值传递:将实参的值复制一份传递给形参,形参在函数内部的修改不会影响实参的值。
- 引用传递:通过在形参前加上
&
符号来定义引用参数,引用参数实际上是实参的别名,函数内部对引用参数的修改会直接影响实参的值,例如void swap(int &a, int &b) {... }
可以实现两个整数的交换。 - 指针传递:将实参的地址传递给形参(指针类型),函数内部通过指针来间接访问和修改实参的值,与引用传递类似,但语法上有所不同,例如
void modify(int *p) { *p = 100; }
。
- 函数的递归调用:函数内部可以调用自身,称为递归调用;递归函数通常需要有一个终止条件,以防止无限递归导致栈溢出;例如计算阶乘的递归函数
int factorial(int n) { if (n == 0 || n == 1) return 1; else return n * factorial(n - 1); }
。
六、结构体与联合体
- 结构体:
- 定义:
struct 结构体名 { 成员变量 1; 成员变量 2;... };
,例如struct Student { char name[20]; int age; float score; };
定义了一个名为Student
的结构体,包含姓名、年龄和成绩三个成员变量。 - 结构体变量的定义与初始化:可以先定义结构体类型,再定义结构体变量,如
Student s1;
,然后对成员变量分别赋值;也可以在定义结构体变量时进行初始化,如Student s2 = {"Tom", 20, 90.5};
。 - 结构体的嵌套:结构体成员变量可以是其他结构体类型,实现复杂的数据结构组合,例如
struct Address { char city[20]; char street[30]; int zipcode; }; struct Person { char name[20]; int age; Address address; };
。 - 结构体指针:可以定义指向结构体的指针,通过指针来访问结构体成员,例如
Student *p = &s1; p->age = 21;
(使用->
运算符访问结构体指针指向的结构体成员)。
- 定义:
- 联合体:
- 定义:
union 联合体名 { 成员变量 1; 成员变量 2;... };
,例如union Data { int num; float fnum; char ch; };
定义了一个名为Data
的联合体。 - 联合体的特点:联合体的所有成员共享同一块内存空间,在某一时刻只能存储其中一个成员的值;联合体的大小取决于其最大成员的大小(考虑内存对齐)。
- 联合体的使用:通常用于节省内存空间,或者在需要根据不同情况复用同一块内存区域来存储不同类型数据时使用;例如在某些通信协议中,根据数据包的类型标志,使用联合体来存储不同格式的数据。
- 定义:
七、类与对象
- 类的定义:
- 基本形式:
class 类名 { private: 私有成员变量和函数; protected: 受保护成员变量和函数; public: 公有成员变量和函数; };
,例如class Circle { private: double radius; public: void setRadius(double r); double getArea(); };
定义了一个名为Circle
的类,包含私有成员变量radius
和公有成员函数setRadius
和getArea
。 - 类的成员函数定义:可以在类体内定义成员函数(内联函数),也可以在类体外定义,类体外定义时需要使用作用域解析运算符
::
来指明函数所属的类,如void Circle::setRadius(double r) { radius = r; } double Circle::getArea() { return 3.14 * radius * radius; }
。
- 基本形式:
- 对象的创建与使用:
- 创建对象:
类名 对象名;
,例如Circle c1;
创建了一个Circle
类的对象c1
。 - 访问成员:通过对象名和
.
运算符访问公有成员变量和函数,如c1.setRadius(5.0); double area = c1.getArea();
;对于指向对象的指针,可以使用->
运算符来访问成员,如Circle *p = &c1; p->setRadius(6.0);
。
- 创建对象:
- 构造函数与析构函数:
- 构造函数:用于对象的初始化,与类名相同,没有返回值类型,可以有参数,在对象创建时自动调用;可以有多个重载的构造函数,以满足不同的初始化需求,例如
Circle(double r) : radius(r) {}
是一个带参数的构造函数,使用初始化列表对成员变量进行初始化,效率更高。 - 析构函数:用于对象销毁时的清理工作,与类名相同,前面加上
~
符号,没有参数和返回值,在对象生命周期结束时自动调用;析构函数主要用于释放对象在构造函数中或生命周期内动态分配的资源,如内存、文件句柄等;如果类中没有动态分配资源,析构函数可以为空。
- 构造函数:用于对象的初始化,与类名相同,没有返回值类型,可以有参数,在对象创建时自动调用;可以有多个重载的构造函数,以满足不同的初始化需求,例如
- 类的继承与多态:
- 继承:通过
: public/protected/private 父类名
的方式实现类的继承,子类可以继承父类的成员变量和函数,例如class Cylinder : public Circle { private: double height; public: void setHeight(double h); double getVolume(); };
,Cylinder
类继承自Circle
类,并新增了成员变量height
和相关成员函数。 - 多态:通过虚函数实现,在父类中的函数前加上
virtual
关键字,子类中重写(覆盖)该虚函数;当通过父类指针或引用指向子类对象时,调用虚函数会根据对象的实际类型来调用相应的子类版本,实现多态行为,例如class Shape { public: virtual double getArea() = 0; }; class Rectangle : public Shape { private: double width; double height; public: Rectangle(double w, double h) : width(w), height(h) {} double getArea() override { return width * height; } };
,Shape
类是抽象类(包含纯虚函数getArea
),Rectangle
类继承自Shape
类并实现了getArea
函数,通过Shape *p = new Rectangle(3, 4); double area = p->getArea();
这种方式实现多态调用。
- 继承:通过
八、模板
- 函数模板:
- 定义:
template <typename T> 函数返回值类型 函数名(T 参数 1, T 参数 2,...) { 函数体; }
,例如template <typename T> T add(T a, T b) { return a + b; }
定义了一个通用的加法函数模板,可以处理不同类型(只要该类型支持加法操作)的参数,如int sum1 = add<int>(3, 5); double sum2 = add<double>(2.5, 3.5);
。
- 定义:
- 类模板:
- 定义:
template <typename T1, typename T2,...> class 类名 {... };
,例如template <typename T> class Stack { private: T data[100]; int top; public: Stack() : top(-1) {} void push(T value); T pop(); };
定义了一个栈类模板,可以存储不同类型的数据,通过Stack<int> s1; Stack<double> s2;
等方式创建不同类型的栈对象,并使用相应的成员函数进行操作。
- 定义:
九、异常处理
- try-catch 语句块:
try
块:包含可能抛出异常的代码,例如try { int a = 5 / 0; // 可能抛出除零异常 }
。catch
块:用于捕获并处理try
块中抛出的异常,catch
后面可以跟异常类型,如catch (const std::exception &e) { std::cerr << "Exception caught: " << e.what() << std::endl; }
可以捕获标准库中的异常类型,并输出异常信息;也可以有多个catch
块来捕获不同类型的异常,按照顺序依次匹配,一旦匹配成功就执行相应的catch
块,然后跳过后续的catch
块;如果没有匹配的catch
块,异常会向上传播到调用栈的上一层,如果一直没有被处理,可能导致程序终止。
- 异常类型:C++ 标准库提供了一些预定义的异常类型,如
std::exception
(所有标准异常的基类)、std::runtime_error
(运行时错误)、std::logic_error
(逻辑错误)等,用户也可以自定义异常类型,通过继承std::exception
类并重载what
函数来提供自定义的异常信息。
十、输入输出流
- 标准输入输出流对象:
std::cin
:用于从标准输入设备(通常是键盘)读取数据,例如int num; std::cin >> num;
可以读取一个整数。std::cout
:用于向标准输出设备(通常是屏幕)输出数据,例如std::cout << "Hello, World!" << std::endl;
输出字符串并换行,endl
是一个操纵符,用于刷新输出缓冲区并换行。std::cerr
:用于输出错误信息到标准错误流,通常与std::cout
类似,但错误信息不会被缓冲,会立即输出,常用于输出程序运行过程中的错误提示和调试信息,如std::cerr << "Error: File not found." << std::endl;
。
- 文件输入输出流:
- 头文件:
<fstream>
提供了文件操作的支持。 std::ifstream
:用于从文件读取数据,例如std::ifstream infile("data.txt"); if (infile.is_open()) { int num; infile >> num; infile.close(); } else { std::cerr << "Error opening file." << std::endl; }
尝试打开一个名为data.txt
的文件,如果成功则读取一个整数并关闭文件,否则输出错误信息。std::ofstream
:用于向文件写入数据,例如 `std::ofstream outfile ("output.txt"); if (outfile.is_open ()) { outfile <<"This is
- 头文件: