# C++ 概览、基础类型与函数

> [!info] 学习导航
> 返回：[[C++ 学习指南]]

**C++ 是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言，支持过程化编程、面向对象编程和泛型编程。**

**C++ 被认为是一种中级语言，它综合了高级语言和低级语言的特点。**

**C++ 是 C 的一个超集，事实上，任何合法的 C 程序都是合法的 C++ 程序。**

**注意：使用静态类型的编程语言是在编译时执行类型检查，而不是在运行时执行类型检查。**

## 面向对象程序设计

**C++ 完全支持面向对象的程序设计，包括面向对象开发的四大特性：**

- **封装（Encapsulation）：封装是将数据和方法组合在一起，对外部隐藏实现细节，只公开对外提供的接口。这样可以提高安全性、可靠性和灵活性。**
- **继承（Inheritance）：继承是从已有类中派生出新类，新类具有已有类的属性和方法，并且可以扩展或修改这些属性和方法。这样可以提高代码的复用性和可扩展性。**
- **多态（Polymorphism）：多态是指同一种操作作用于不同的对象，可以有不同的解释和实现。它可以通过接口或继承实现，可以提高代码的灵活性和可读性。**
- **抽象（Abstraction）：抽象是从具体的实例中提取共同的特征，形成抽象类或接口，以便于代码的复用和扩展。抽象类和接口可以让程序员专注于高层次的设计和业务逻辑，而不必关注底层的实现细节。**

## 标准库

**标准的 C++ 由三个重要部分组成：**

- **核心语言，提供了所有构件块，包括变量、数据类型和常量，等等。**
- **C++ 标准库，提供了大量的函数，用于操作文件、字符串等。**
- **标准模板库（STL），提供了大量的方法，用于操作数据结构等。**

**C++ 程序可以定义为对象的集合，这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象，方法、即时变量。**

- **对象 - 对象具有状态和行为。对象是类的实例。**
- **类 - 类可以定义为描述对象行为/状态的模板/蓝图。**
- **方法 - 从基本上说，一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。**
- **即时变量 - 每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。**

## C++ 与 Python 的类型差异

| **特性**               | **C**                 | **C++**                    | **Python**              |
| ---------------------- | --------------------- | -------------------------- | ----------------------- |
| **int/double等类型**   | **基本类型**          | **基本类型**               | **类（对象）**          |
| **是否有成员函数**     | **❌ 否**              | **❌ 基本类型否，类类型有** | **✅ 是（如x.real）**    |
| **类型本身是否为对象** | **❌ 否**              | **❌ 否**                   | **✅ 是（type(x)）**     |
| **类型**               | **C语言**             | **C++**                    | **Python**              |
| **字符串**             | **char[]（非类）**    | **std::string（类）**      | **str类（一切皆对象）** |
| **布尔值**             | **_Bool/int（非类）** | **bool（基本类型，非类）** | **bool类（int的子类）** |


- **Python：一切皆对象，通过类统一接口，牺牲性能换取灵活性和简洁性。**


## 标识符

**标识符是用来标识变量、函数、类、模块，或任何其他用户自定义项目的名称。一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始，后跟零个或多个字母、下划线和数字（0-9）。**

**C++ 标识符内不允许出现标点字符，比如 @、& 和 %。C++ 是区分大小写的编程语言。保留字不能作为常量名、变量名或其他标识符名称。**

## 基本内置类型

**C++ 为程序员提供了种类丰富的内置数据类型和用户自定义的数据类型。下表列出了七种基本的 C++ 数据类型：**

| **类型**     | **关键字**  |
| ------------ | ----------- |
| **布尔型**   | **bool**    |
| **字符型**   | **char**    |
| **整型**     | **int**     |
| **浮点型**   | **float**   |
| **双浮点型** | **double**  |
| **无类型**   | **void**    |
| **宽字符型** | **wchar_t** |

**C++ 修饰符类型**

**C++ 允许在 char、int 和 double 数据类型前放置修饰符。**

**修饰符是用于改变变量类型的行为的关键字，它更能满足各种情境的需求。**

**一些基本类型可以使用一个或多个类型修饰符进行修饰**

**如前四种**

**C++ 中的类型限定符**

**类型限定符提供了变量的额外信息，用于在定义变量或函数时改变它们的默认行为的关键字。**

**后五种**

| **修饰符**   | **描述**                                                     | **示例**                  |
| ------------ | ------------------------------------------------------------ | ------------------------- |
| **signed**   | **表示有符号类型（默认）**                                   | **signed  int x = -10;**  |
| **unsigned** | **表示无符号类型**                                           | **unsigned  int y = 10;** |
| **short**    | **表示短整型**                                               | **short  int z = 100;**   |
| **long**     | **表示长整型**                                               | **long  int a = 100000;** |
| **const**    | **表示常量，值不可修改**                                     | **const  int b = 5;**     |
| **volatile** | **表示变量可能被意外修改，禁止编译器优化**                   | **volatile  int c = 10;** |
| **mutable**  | **表示类成员可以在 const 对象中修改**                        | **mutable  int counter;** |
| **restrict** | **由 restrict 修饰的指针是唯一一种访问它所指向的对象的方式。只有 C99 增加了新的类型限定符 restrict。** |                           |
| **static**   | **用于定义静态变量，表示该变量的作用域仅限于当前文件或当前函数内，不会被其他文件或函数访问。** |                           |


**C++11 新增类型**

| **数据类型**              | **描述**                               | **示例**                                          |
| ------------------------- | -------------------------------------- | ------------------------------------------------- |
| **auto**                  | **自动类型推断**                       | **auto  x = 10;**                                 |
| **decltype**              | **获取表达式的类型**                   | **decltype(x)  y = 20;**                          |
| **nullptr**               | **空指针常量**                         | **int\*  ptr = nullptr;**                         |
| **std::initializer_list** | **初始化列表类型**                     | **std::initializer_list\<int>  list = {1, 2, 3};** |
| **std::tuple**            | **元组类型，可以存储多个不同类型的值** | **std::tuple\<int,  float, char> t(1, 2.0, 'a');** |

**派生数据类型**

| **数据类型**      | **描述**                                           | **示例**                              |
| ----------------- | -------------------------------------------------- | ------------------------------------- |
| **数组**          | **相同类型元素的集合**                             | **int  arr[5] = {1, 2, 3, 4, 5};**    |
| **指针**          | **存储变量内存地址的类型**                         | **int\*  ptr = &x;**                  |
| **引用**          | **变量的别名**                                     | **int&  ref = x;**                    |
| **函数**          | **函数类型，表示函数的签名**                       | **int  func(int a, int b);**          |
| **结构体**        | **用户定义的数据类型，可以包含多个不同类型的成员** | **struct  Point { int x; int y; };**  |
| **类**            | **用户定义的数据类型，支持封装、继承和多态**       | **class  MyClass { ... };**           |
| **联合体/共用体** | **多个成员共享同一块内存**                         | **union  Data { int i; float f; };**  |
| **枚举**          | **用户定义的整数常量集合**                         | **enum  Color { RED, GREEN, BLUE };** |

**类型别名**

| **别名**    | **描述**                             | **示例**                |
| ----------- | ------------------------------------ | ----------------------- |
| **typedef** | **为现有类型定义别名**               | **typedef  int MyInt;** |
| **using**   | **为现有类型定义别名（C++11 引入）** | **using  MyInt = int;** |

**标准库类型**

| **数据类型**    | **描述**                       | **示例**                               |
| --------------- | ------------------------------ | -------------------------------------- |
| **std::string** | **字符串类型**                 | **std::string  s = "Hello";**          |
| **std::vector** | **动态数组**                   | **std::vector\<int>  v = {1, 2, 3};**   |
| **std::array**  | **固定大小数组（C++11 引入）** | **std::array\<int,  3> a = {1, 2, 3};** |
| **std::pair**   | **存储两个值的容器**           | **std::pair\<int,  float> p(1, 2.0);**  |
| **std::map**    | **键值对容器**                 | **std::map\<int,  std::string> m;**     |
| **std::set**    | **唯一值集合**                 | **std::set\<int>  s = {1, 2, 3};**      |


| **方式**       | **类型安全** | **可读性** | **标准一致性** |
| -------------- | ------------ | ---------- | -------------- |
| **true/false** | **✅ 最佳**   | **✅ 最佳** | **✅ C++标准**  |
| **隐式判断**   | **✅ 好**     | **✅ 简洁** | **✅ 推荐**     |
| **1/0**        | **❌ 弱**     | **❌ 差**   | **⚠️ C遗留**    |
| **TRUE/FALSE** | **⚠️ 依赖宏** | **❌ 过时** | **⚠️ 兼容C**    |


## typedef 声明

**您可以使用 typedef 为一个已有的类型取一个新的名字。下面是使用 typedef 定义一个新类型的语法：**

```cpp
typedef type newname;
```

## 枚举类型（enumeration）

**是C++中的一种派生数据类型，它是由用户定义的若干枚举常量的集合。**

**如果一个变量只有几种可能的值，可以定义为枚举(enumeration)类型。所谓"枚举"是指将变量的值一一列举出来，变量的值只能在列举出来的值的范围内。**

**创建枚举，需要使用关键字 enum。枚举类型的一般形式为：**

```cpp
enum 枚举名{
```

   **标识符[=整型常数],**

   **标识符[=整型常数],**

**...**

  **标识符[=整型常数]**

```cpp
} 枚举变量;
```

**如果枚举没有初始化, 即省掉"=整型常数"时, 则从第一个标识符开始。**

**例如，下面的代码定义了一个颜色枚举，变量 c 的类型为 color。最后，c 被赋值为 "blue"。**

```cpp
enum color { red, green, blue } c;
c = blue;
```

**1. c 的类型是什么？**

**c 的类型是 enum color（C语言）**

**2. red/green/blue 是什么类型？**

**它们是整型常量（int），不是字符串**

**类型转换**

**类型转换是将一个数据类型的值转换为另一种数据类型的值。**

**C++ 中有四种类型转换：静态转换、动态转换、常量转换和重新解释转换。**

**3、**

**enum color 的底层是整数类型（通常是 int）
 虽然 c 的类型名义上是 enum color，但它的存储方式和操作完全按照整数处理：**

```cpp
printf("%d", c); // 输出 2（blue 的值）
```

**枚举值（red/green/blue）本质是编译时的整型常量（red=0, green=1, blue=2）。**

## 函数


函数是一组一起执行一个任务的语句。每个 C++ 程序都至少有一个函数，即主函数 main() ，所有简单的程序都可以定义其他额外的函数。


您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的，但在逻辑上，划分通常是根据每个函数执行一个特定的任务来进行的。


函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实际主体。


C++ 标准库提供了大量的程序可以调用的内置函数。例如，函数 strcat() 用来连接两个字符串，函数 memcpy() 用来复制内存到另一个位置。


函数还有很多叫法，比如方法、子例程或程序，等等。


定义函数

C++ 中的函数定义的一般形式如下：


```cpp
return_type function_name( parameter list )
{
```

  body of the function

```cpp
}
```

在 C++ 中，函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分：


返回类型：一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值，在这种情况下，return_type 是关键字 void。

函数名称：这是函数的实际名称。函数名和参数列表一起构成了函数签名。

参数：参数就像是占位符。当函数被调用时，您向参数传递一个值，这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的，也就是说，函数可能不包含参数。

函数主体：函数主体包含一组定义函数执行任务的语句。

实例

以下是 max() 函数的源代码。该函数有两个参数 num1 和 num2，会返回这两个数中较大的那个数：


函数声明

函数声明会告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。


函数声明包括以下几个部分：


```cpp
return_type function_name( parameter list );
```

针对上面定义的函数 max()，以下是函数声明：


```cpp
int max(int num1, int num2);
```

在函数声明中，参数的名称并不重要，只有参数的类型是必需的，因此下面也是有效的声明：


```cpp
int max(int, int);
```

当您在一个源文件中定义函数且在另一个文件中调用函数时，函数声明是必需的。在这种情况下，您应该在调用函数的文件顶部声明函数。


调用函数

创建 C++ 函数时，会定义函数做什么，然后通过调用函数来完成已定义的任务。


当程序调用函数时，程序控制权会转移给被调用的函数。被调用的函数执行已定义的任务，当函数的返回语句被执行时，或到达函数的结束括号时，会把程序控制权交还给主程序。


调用函数时，传递所需参数，如果函数返回一个值，则可以存储返回值。例如：

**函数参数**

如果函数要使用参数，则必须声明接受参数值的变量。这些变量称为函数的**形式参数**。

形式参数就像函数内的其他局部变量，在进入函数时被创建，退出函数时被销毁。

当调用函数时，有三种向函数传递参数的方式：

**参数的默认值**

当您定义一个函数，您可以为参数列表中后边的每一个参数指定默认值。当调用函数时，如果实际参数的值留空，则使用这个默认值。

这是通过在函数定义中使用赋值运算符来为参数赋值的。调用函数时，如果未传递参数的值，则会使用默认值，如果指定了值，则会忽略默认值，使用传递的值。请看下面的实例：

C++规定，设定函数形参默认值时，必须从函数最右边的形参开始，只有右边无形参或右边形参已经设定默认值时，左边形参才能设定默认值

函数调用时，缺省实参一样从右边开始，只有右边实参缺省时，左边实参才能缺省

如果函数由声明，已提供参数默认值，函数定义时不可重复提供参数默认值

函数调用实参缺省时，用于分隔实参的逗号也同样缺省

---

## 学习导航

- 返回目录：[[C++ 学习指南]]
- 下一篇：[[计算机系/C++/02 类型转换、变量与生命周期|类型转换、变量与生命周期]]
