# C++ 类核心知识完整总结

# C++ 类核心知识完整总结

> 本文是个人学习笔记，理解可能有误，欢迎指正！

## 目录

1.  [类的基本结构与访问控制](#1-%E7%B1%BB%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84%E4%B8%8E%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6)
    
2.  [构造函数（Constructor）](#2-%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0constructor)
    
3.  [析构函数（Destructor）](#3-%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0destructor)
    
4.  [构造函数的进阶用法](#4-%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E7%9A%84%E8%BF%9B%E9%98%B6%E7%94%A8%E6%B3%95)
    
5.  [对象的生命周期与构造/析构执行顺序](#5-%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E4%B8%8E%E6%9E%84%E9%80%A0%E6%9E%90%E6%9E%84%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F)
    
6.  [类的其他核心要点](#6-%E7%B1%BB%E7%9A%84%E5%85%B6%E4%BB%96%E6%A0%B8%E5%BF%83%E8%A6%81%E7%82%B9)
    
7.  [总结](#7-%E6%80%BB%E7%BB%93)
    

## 1\. 类的基本结构与访问控制

类是 C++ 面向对象编程的核心，用于**封装**数据（成员变量）和操作数据的行为（成员函数）。类的定义以`class`关键字开头，主体包含在大括号`{}`中，末尾必须加分号`;`。

### 1.1 基础结构代码示例

```cpp
#include <iostream>
#include <string>
using namespace std;

class Person {
    // 1. 私有成员（默认权限）：仅类内部可访问，外部不可直接操作
private:
    string name;  // 私有成员变量：封装核心数据，避免外部直接修改
    int age;

    // 2. 保护成员：类内部 + 子类可访问，外部不可访问
protected:
    string gender;

    // 3. 公有成员：类内部 + 外部可访问，是类对外的接口
public:
    // 构造函数、析构函数、普通成员函数的声明（必须放在public中）
    Person();                  // 无参构造函数
    Person(string n, int a);   // 有参构造函数（重载）
    ~Person();                 // 析构函数

    void setInfo(string n, int a); // 成员函数：操作私有数据的接口
    void showInfo();             // 成员函数：展示对象数据
};
```

### 1.2 访问权限核心规则

| 权限关键字 | 访问范围 | 核心用途 |
| --- | --- | --- |
| private | 仅类内部 | 封装核心数据，杜绝外部直接修改 |
| public | 类内部 + 外部（对象/指针） | 对外提供操作接口（构造/成员函数） |
| protected | 类内部 + 子类 | 为继承场景预留访问权限 |

## 2\. 构造函数（Constructor）

构造函数是类的特殊成员函数，**核心作用是初始化对象**，在创建对象时自动调用，无法手动调用。

### 2.1 核心特性

*   **命名规则**：函数名与类名完全一致，无返回值（连`void`都不能写）；
    
*   **自动调用**：创建对象时（如`Person p;`/`Person p("张三", 20);`）立即执行；
    
*   **支持重载**：可定义多个构造函数，通过参数列表（个数、类型、顺序）区分；
    
*   **默认构造**：若未手动定义任何构造函数，编译器会自动生成无参默认构造（空实现）；若手动定义了构造函数，编译器不再生成默认构造。
    

### 2.2 代码实现（类内声明 + 类外定义）

```cpp
// 1. 无参构造函数（初始化默认值）
Person::Person() {
    name = "未知";
    age = 0;
    gender = "未知";
    cout << "无参构造函数被调用，对象初始化完成" << endl;
}

// 2. 有参构造函数（自定义初始化值）
Person::Person(string n, int a) {
    name = n;
    age = a;
    gender = "未知";
    cout << "有参构造函数被调用，对象初始化完成" << endl;
}

// 3. 成员函数：操作私有数据的接口
void Person::setInfo(string n, int a) {
    name = n;
    age = a;
}

void Person::showInfo() {
    cout << "姓名：" << name << "，年龄：" << age << endl;
}
```

## 3\. 析构函数（Destructor）

析构函数是类的特殊成员函数，**核心作用是清理对象占用的资源**（如动态内存、打开的文件、网络连接等），在对象生命周期结束时自动调用。

### 3.1 核心特性

*   **命名规则**：`~类名()`，无返回值、无参数，**不能重载**（一个类只能有一个析构函数）；
    
*   **自动调用**：对象销毁时执行（局部对象出作用域、动态对象被`delete`、程序结束）；
    
*   **默认析构**：若未手动定义，编译器生成空实现的默认析构；若对象占用动态资源（`new`分配的内存），必须手动编写析构函数释放资源，避免内存泄漏。
    

### 3.2 代码实现（含资源释放示例）

```cpp
// 1. 基础析构函数
Person::~Person() {
    cout << "析构函数被调用，对象 " << name << " 已销毁" << endl;
}

// 2. 带动态资源的析构示例（重点：避免内存泄漏）
class Student {
private:
    string* major; // 动态分配的字符串（堆区内存）
public:
    // 构造函数：分配堆区内存
    Student(string m) {
        major = new string(m); // 堆区分配内存
        cout << "Student 构造，分配专业内存" << endl;
    }

    // 析构函数：必须释放堆区内存
    ~Student() {
        delete major; // 释放动态内存，避免内存泄漏
        cout << "Student 析构，释放专业内存" << endl;
    }

    void showMajor() {
        cout << "专业：" << *major << endl;
    }
};
```

## 4\. 构造函数的进阶用法

### 4.1 拷贝构造函数

用于**用一个已存在的对象初始化新对象**，是构造函数的一种重载形式，格式为：`类名(const 类名& 源对象)`。

#### 4.1.1 代码实现

```cpp
// 拷贝构造函数声明（类内）
class Person {
    // 省略其他成员...
public:
    Person(const Person& p); // 拷贝构造函数声明
};

// 拷贝构造函数定义（类外）
Person::Person(const Person& p) {
    name = p.name;
    age = p.age;
    gender = p.gender;
    cout << "拷贝构造函数被调用" << endl;
}

// 拷贝构造的使用场景
int main() {
    Person p1("李四", 25); // 调用有参构造
    Person p2 = p1;        // 场景1：赋值初始化，调用拷贝构造
    Person p3(p1);         // 场景2：直接初始化，调用拷贝构造
    return 0;
}
```

### 4.2 初始化列表（推荐用法）

更高效的对象初始化方式，**直接初始化成员变量**（而非在构造函数体内赋值），避免“先默认初始化、再赋值”的二次操作，尤其适合常量成员、引用成员的初始化。

#### 4.2.1 代码实现

```cpp
// 用初始化列表改写有参构造函数
Person::Person(string n, int a) 
    : name(n), age(a), gender("未知") { // 初始化列表：直接给成员变量赋值
    cout << "初始化列表版构造函数被调用" << endl;
}
```

## 5\. 对象的生命周期与构造/析构执行顺序

对象的生命周期决定了构造函数和析构函数的执行时机，不同类型的对象（局部、动态）执行顺序不同。

### 5.1 完整代码示例

```cpp
int main() {
    cout << "===== 局部对象 =====" << endl;
    Person p1;          // 调用无参构造
    Person p2("王五", 30); // 调用有参构造
    p2.showInfo();

    cout << "===== 动态对象 =====" << endl;
    Person* p3 = new Person("赵六", 35); // 调用有参构造
    p3->showInfo();
    delete p3; // 手动释放动态对象，触发析构函数

    cout << "===== 主函数结束 =====" << endl;
    return 0; // 局部对象 p1、p2 出作用域，依次调用析构函数
}
```

### 5.2 执行结果顺序

```Plain
===== 局部对象 =====
无参构造函数被调用，对象初始化完成
有参构造函数被调用，对象初始化完成
姓名：王五，年龄：30
===== 动态对象 =====
有参构造函数被调用，对象初始化完成
姓名：赵六，年龄：35
析构函数被调用，对象 赵六 已销毁
===== 主函数结束 =====
析构函数被调用，对象 王五 已销毁
析构函数被调用，对象 未知 已销毁
```

### 5.3 核心规律

*   局部对象：构造 → 出作用域 → 析构（先创建后销毁）；
    
*   动态对象：`new` → 构造 → `delete` → 析构（手动释放才会析构，否则内存泄漏）；
    
*   全局对象：程序启动时构造 → 程序结束时析构。
    

## 6\. 类的其他核心要点

### 6.1 封装性

通过`private`隐藏内部数据，仅通过`public`成员函数对外提供访问接口，保证数据安全性（比如可以在`setInfo`中校验年龄的合法性）。

### 6.2 this指针

每个非静态成员函数都隐含一个`this`指针，指向当前调用函数的对象，可用于区分成员变量和参数：

```cpp
void Person::setInfo(string name, int age) {
    this->name = name; // this->name 是成员变量，name 是参数
    this->age = age;
}
```

### 6.3 静态成员

用`static`修饰的成员变量/函数，**属于类本身**（而非单个对象），所有对象共享，可通过`类名::成员名`直接访问：

```cpp
class Person {
public:
    static int count; // 静态成员变量：统计对象数量
    Person() { count++; } // 构造时计数+1
    static void showCount() { // 静态成员函数：访问静态成员
        cout << "对象总数：" << count << endl;
    }
};
// 静态成员变量必须在类外初始化
int Person::count = 0;

// 使用示例
int main() {
    Person p1, p2;
    Person::showCount(); // 输出：对象总数：2
    return 0;
}
```

### 6.4 const成员函数

函数末尾加`const`，表示该函数**不会修改对象的成员变量**，仅做只读操作：

```cpp
class Person {
public:
    void showInfo() const { // const成员函数
        cout << "姓名：" << name << "，年龄：" << age << endl;
        // age = 100; // 错误：const函数不能修改成员变量
    }
};
```

## 7\. 总结

1.  **构造函数**：与类同名、无返回值、支持重载，创建对象时自动调用，核心作用是初始化对象；初始化列表是更高效的初始化方式，推荐优先使用。
    
2.  **析构函数**：格式为`~类名()`、无参数、不能重载，对象销毁时自动调用；若对象占用动态资源（如`new`内存），必须手动实现析构函数释放资源，避免内存泄漏。
    
3.  **类的核心特性**：封装性通过`private/public/protected`控制数据访问，`this`指针指向当前对象，静态成员属于类本身，`const`成员函数保证只读操作。
