首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >小智AI ESP32S3 学习课件 - 第3周:C++ 基础与面向对象思维

小智AI ESP32S3 学习课件 - 第3周:C++ 基础与面向对象思维

作者头像
网罗开发
发布2025-11-14 13:49:19
发布2025-11-14 13:49:19
300
举报
文章被收录于专栏:网罗开发网罗开发

📚 本周学习目标

  • 理解 C vs C++ 的区别和优势
  • 掌握类与对象、构造函数与析构函数
  • 学习单例模式在 Application 类中的使用
  • 快速掌握 STL 容器使用
  • 完成 LED 控制类的上机练习
  • 附加内容

🎯 第3课:C++ 基础与面向对象思维

3.1 C vs C++:为什么这个工程用 C++

C 语言 vs C++ 语言对比

C语言特点

代码语言:javascript
复制
C语言特点:
├── 过程化编程
├── 函数式设计
├── 手动内存管理
├── 简单直接
└── 性能高效

C++语言特点

代码语言:javascript
复制
C++语言特点:
├── 面向对象编程
├── 类与对象
├── 自动内存管理
├── 丰富的标准库
└── 更好的代码组织
为什么小智 AI 项目选择 C++?

项目需求分析

代码语言:javascript
复制
项目需求:
├── 复杂的硬件抽象
├── 多层次的设备管理
├── 音频处理管道
├── 网络协议处理
└── 物联网设备控制

C++优势

代码语言:javascript
复制
C++优势:
├── 面向对象设计
│   ├── 更好的代码组织
│   ├── 清晰的职责分离
│   └── 易于维护和扩展
├── 丰富的标准库
│   ├── STL容器
│   ├── 智能指针
│   └── 算法库
├── 模板支持
│   ├── 泛型编程
│   ├── 代码复用
│   └── 类型安全
└── 现代C++特性
    ├── 自动类型推导
    ├── Lambda表达式
    └── 移动语义
项目中的 C++ 特性应用

面向对象设计

代码语言:javascript
复制
// 抽象基类设计
class Board {
public:
    virtual ~Board() = default;
    virtual std::string GetBoardType() = 0;
    virtual AudioCodec* GetAudioCodec() = 0;
    virtual Display* GetDisplay() = 0;
};

// 具体实现类
class WifiBoard :public Board {
public:
    std::string GetBoardType() override {
        return"wifi";
    }
    // 其他实现...
};

智能指针使用

代码语言:javascript
复制
// 自动内存管理
std::unique_ptr<OpusEncoderWrapper> opus_encoder_;
std::unique_ptr<OpusDecoderWrapper> opus_decoder_;
std::unique_ptr<Protocol> protocol_;

STL容器使用

代码语言:javascript
复制
// 容器使用
std::list<std::function<void()>> main_tasks_;
std::list<std::vector<uint8_t>> audio_decode_queue_;
std::vector<Thing*> things_;

3.2 类与对象、构造函数与析构函数

类与对象基础

类的定义

代码语言:javascript
复制
// 类定义示例
class Led {
public:
    // 构造函数
    Led(gpio_num_t gpio);
    
    // 析构函数
    virtual ~Led() = default;
    
    // 成员函数
    virtual void OnStateChanged() = 0;
    
private:
    // 成员变量
    gpio_num_t gpio_;
    bool state_;
};

对象创建和使用

代码语言:javascript
复制
// 对象创建
Led* led = new SingleLed(GPIO_NUM_2);

// 对象使用
led->OnStateChanged();

// 对象销毁
delete led;
构造函数详解

构造函数类型

代码语言:javascript
复制
class AudioCodec {
public:
    // 默认构造函数
    AudioCodec() = default;
    
    // 参数化构造函数
    AudioCodec(int sample_rate, int channels) 
        : sample_rate_(sample_rate), channels_(channels) {
        ESP_LOGI(TAG, "AudioCodec created with sample_rate=%d, channels=%d", 
                 sample_rate_, channels_);
    }
    
    // 拷贝构造函数
    AudioCodec(const AudioCodec& other) 
        : sample_rate_(other.sample_rate_), channels_(other.channels_) {
        ESP_LOGI(TAG, "AudioCodec copied");
    }
    
    // 移动构造函数
    AudioCodec(AudioCodec&& other) noexcept
        : sample_rate_(other.sample_rate_), channels_(other.channels_) {
        other.sample_rate_ = 0;
        other.channels_ = 0;
        ESP_LOGI(TAG, "AudioCodec moved");
    }

private:
    int sample_rate_;
    int channels_;
};

初始化列表

代码语言:javascript
复制
class Display {
public:
    Display(int width, int height, DisplayFonts fonts)
        : width_(width), height_(height), fonts_(fonts) {
        // 初始化逻辑
        Initialize();
    }

private:
    int width_;
    int height_;
    DisplayFonts fonts_;
};
析构函数详解

析构函数作用

代码语言:javascript
复制
class Protocol {
public:
    Protocol() {
        ESP_LOGI(TAG, "Protocol created");
    }
    
    virtual ~Protocol() {
        ESP_LOGI(TAG, "Protocol destroyed");
        // 清理资源
        if (websocket_handle_) {
            esp_websocket_client_destroy(websocket_handle_);
        }
    }

private:
    esp_websocket_client_handle_t websocket_handle_;
};

虚析构函数

代码语言:javascript
复制
// 基类使用虚析构函数
class Board {
public:
    virtual ~Board() = default;  // 虚析构函数
};

// 派生类
class WifiBoard : public Board {
public:
    ~WifiBoard() override {
        ESP_LOGI(TAG, "WifiBoard destroyed");
        // 清理WiFi相关资源
    }
};

3.3 单例模式在 Application 类中的使用

单例模式基础

什么是单例模式?

代码语言:javascript
复制
单例模式特点:
├── 确保类只有一个实例
├── 提供全局访问点
├── 延迟初始化
└── 线程安全

单例模式实现方式

代码语言:javascript
复制
// 方式1:懒汉式(线程不安全)
class Application {
public:
    static Application& GetInstance() {
        static Application instance;
        return instance;
    }
    
private:
    Application() = default;
    Application(const Application&) = delete;
    Application& operator=(const Application&) = delete;
};

小智AI项目中的单例模式

代码语言:javascript
复制
// Application类单例实现
class Application {
public:
    static Application& GetInstance() {
        static Application instance;
        return instance;
    }
    
    // 禁止拷贝和赋值
    Application(const Application&) = delete;
    Application& operator=(const Application&) = delete;

private:
    Application() {
        ESP_LOGI(TAG, "Application singleton created");
    }
    
    ~Application() {
        ESP_LOGI(TAG, "Application singleton destroyed");
    }
};
单例模式的优势

资源管理

代码语言:javascript
复制
class Application {
public:
    void Start() {
        // 获取单例实例
        auto& board = Board::GetInstance();
        auto& thing_manager = ThingManager::GetInstance();
        
        // 使用单例实例
        board.Initialize();
        thing_manager.Initialize();
    }
};

全局访问

代码语言:javascript
复制
// 在任何地方都可以访问Application实例
void SomeFunction() {
    auto& app = Application::GetInstance();
    app.SetDeviceState(kDeviceStateIdle);
}
其他单例模式应用

Board类单例

代码语言:javascript
复制
class Board {
public:
    static Board& GetInstance() {
        static Board* instance = static_cast<Board*>(create_board());
        return *instance;
    }
};

ThingManager类单例

代码语言:javascript
复制
class ThingManager {
public:
    static ThingManager& GetInstance() {
        static ThingManager instance;
        return instance;
    }
};

3.4 快速过一遍 STL

STL 容器介绍

vector容器

代码语言:javascript
复制
// vector 使用示例
std::vector<int> numbers = {1, 2, 3, 4, 5};

// 添加元素
numbers.push_back(6);

// 访问元素
int first = numbers[0];
int last = numbers.back();

// 遍历
for (const auto& num : numbers) {
    ESP_LOGI(TAG, "Number: %d", num);
}

list容器

代码语言:javascript
复制
// list使用示例
std::list<std::function<void()>> tasks;

// 添加任务
tasks.push_back([]() {
    ESP_LOGI(TAG, "Task executed");
});

// 执行任务
for (auto& task : tasks) {
    task();
}

map容器

代码语言:javascript
复制
// map使用示例
std::map<std::string, int> device_states;

// 添加键值对
device_states["idle"] = 0;
device_states["listening"] = 1;
device_states["speaking"] = 2;

// 查找值
auto it = device_states.find("idle");
if (it != device_states.end()) {
    ESP_LOGI(TAG, "State value: %d", it->second);
}
STL 算法使用

排序算法

代码语言:javascript
复制
#include <algorithm>

std::vector<int> numbers = {5, 2, 8, 1, 9};

// 排序
std::sort(numbers.begin(), numbers.end());

// 查找
auto it = std::find(numbers.begin(), numbers.end(), 5);
if (it != numbers.end()) {
    ESP_LOGI(TAG, "Found 5 at position: %ld", std::distance(numbers.begin(), it));
}

Lambda 表达式

代码语言:javascript
复制
// Lambda表达式使用
std::vector<int> numbers = {1, 2, 3, 4, 5};

// 使用Lambda表达式过滤
std::vector<int> even_numbers;
std::copy_if(numbers.begin(), numbers.end(), 
             std::back_inserter(even_numbers),
             [](int n) { return n % 2 == 0; });
智能指针使用

unique_ptr

代码语言:javascript
复制
// unique_ptr使用
std::unique_ptr<OpusEncoderWrapper> opus_encoder_;

// 创建对象
opus_encoder_ = std::make_unique<OpusEncoderWrapper>(16000, 1, 60);

// 使用对象
opus_encoder_->Encode(audio_data, callback);

shared_ptr

代码语言:javascript
复制
// shared_ptr使用
std::shared_ptr<AudioCodec> codec_;

// 创建对象
codec_ = std::make_shared<Es8311AudioCodec>();

// 共享对象
auto codec_copy = codec_;

3.5 上机练习:写一个简单的类,封装 LED 开关

实验目标
  • 创建一个 LED 控制类
  • 实现 LED 开关功能
  • 理解面向对象编程思想
实验步骤

步骤1:创建主程序

代码语言:javascript
复制
// main/main.cpp
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_system.h"

staticconstchar *TAG = "main";

// LED控制结构体
typedefstruct {
    gpio_num_t gpio;
    bool active_high;
    bool current_state;
} led_control_t;

// LED控制函数
void led_init(led_control_t *led, gpio_num_t gpio, bool active_high) {
    led->gpio = gpio;
    led->active_high = active_high;
    led->current_state = false;
    
    // 配置GPIO
    gpio_config_t io_conf = {};
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = (1ULL << gpio);
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
    
    gpio_config(&io_conf);
    
    // 初始状态为关闭
    gpio_set_level(gpio, active_high ? 0 : 1);
    
    ESP_LOGI(TAG, "LED control initialized on GPIO %d", gpio);
}

void led_turn_on(led_control_t *led) {
    gpio_set_level(led->gpio, led->active_high ? 1 : 0);
    led->current_state = true;
    ESP_LOGI(TAG, "LED turned ON");
}

void led_turn_off(led_control_t *led) {
    gpio_set_level(led->gpio, led->active_high ? 0 : 1);
    led->current_state = false;
    ESP_LOGI(TAG, "LED turned OFF");
}

void led_toggle(led_control_t *led) {
    if (led->current_state) {
        led_turn_off(led);
    } else {
        led_turn_on(led);
    }
}

void led_set_state(led_control_t *led, bool state) {
    if (state) {
        led_turn_on(led);
    } else {
        led_turn_off(led);
    }
}

bool led_get_state(led_control_t *led) {
    return led->current_state;
}

void app_main(void) {
    ESP_LOGI(TAG, "Starting LED control example");
    
    // 创建LED控制对象
    led_control_t led;
    led_init(&led, GPIO_NUM_2, true);  // GPIO2, 高电平有效
    
    // 测试LED功能
    ESP_LOGI(TAG, "Testing LED control...");
    
    // 打开LED
    led_turn_on(&led);
    vTaskDelay(pdMS_TO_TICKS(1000));
    
    // 关闭LED
    led_turn_off(&led);
    vTaskDelay(pdMS_TO_TICKS(1000));
    
    // 切换LED状态
    led_toggle(&led);
    vTaskDelay(pdMS_TO_TICKS(1000));
    
    // 设置LED状态
    led_set_state(&led, true);
    vTaskDelay(pdMS_TO_TICKS(1000));
    
    // 获取LED状态
    bool state = led_get_state(&led);
    ESP_LOGI(TAG, "Current LED state: %s", state ? "ON" : "OFF");
    
    // 循环闪烁
    ESP_LOGI(TAG, "Starting LED blink loop...");
    int count = 0;
    while (1) {
        led_toggle(&led);
        ESP_LOGI(TAG, "LED blink count: %d", count++);
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

步骤2:配置项目

代码语言:javascript
复制
# CMakeLists.txt
cmake_minimum_required(VERSION 3.16)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(led_control_example)

步骤3:编译和烧录

代码语言:javascript
复制
# 设置环境
get_idf

# 设置目标芯片
idf.py set-target esp32s3

# 编译项目
idf.py build

# 烧录程序
idf.py -p COM3 flash monitor

步骤4:观察结果

代码语言:javascript
复制
期望输出:
I (1234) main: Starting LED control example
I (1235) led_control: LED control initialized on GPIO 2
I (1236) main: Testing LED control...
I (1237) led_control: LED turned ON
I (2237) led_control: LED turned OFF
I (3237) led_control: LED turned ON
I (4237) led_control: LED turned ON
I (4238) main: Current LED state: ON
I (4239) main: Starting LED blink loop...
I (4240) led_control: LED turned OFF
I (4241) main: LED blink count: 0
I (4741) led_control: LED turned ON
I (4742) main: LED blink count: 1
...
实验总结

掌握内容

  • ✅ 类的定义和实现
  • ✅ 构造函数和析构函数
  • ✅ 成员函数和成员变量
  • ✅ 对象创建和使用
  • ✅ 面向对象编程思想

扩展练习

  1. 添加LED亮度控制功能
  2. 实现LED呼吸灯效果
  3. 添加LED状态指示功能
  4. 创建多个LED控制对象

学习资源

  • C++教程
  • STL参考
  • 设计模式

附加内容

main.c文件中的每一行代码进行详细解析说明:

头文件包含部分

代码语言:javascript
复制
#include <stdio.h>
  • 作用:包含标准输入输出库
  • 用途:提供 printfscanf等标准I/O函数(虽然这里没有直接使用,但通常包含以备用)
代码语言:javascript
复制
#include "freertos/FreeRTOS.h"
  • 作用:包含FreeRTOS实时操作系统核心头文件
  • 用途:提供FreeRTOS的基本数据类型、宏定义和核心功能
代码语言:javascript
复制
#include "freertos/task.h"
  • 作用:包含FreeRTOS任务管理头文件
  • 用途:提供任务创建、删除、延时等函数,如 vTaskDelay()
代码语言:javascript
复制
#include "driver/gpio.h"
  • 作用:包含ESP32 GPIO驱动头文件
  • 用途:提供GPIO配置和控制函数,如 gpio_config()gpio_set_level()
代码语言:javascript
复制
#include "esp_log.h"
  • 作用:包含ESP-IDF日志系统头文件
  • 用途:提供日志输出函数,如 ESP_LOGI()
代码语言:javascript
复制
#include "esp_system.h"
  • 作用:包含ESP32系统相关头文件
  • 用途:提供系统级功能和定义

全局变量定义

代码语言:javascript
复制
static const char *TAG = "main";
  • 作用:定义日志标签
  • 用途:用于标识日志输出的来源模块,所有日志都会显示 [main]前缀
  • static:限制作用域仅在当前文件内

数据结构定义

代码语言:javascript
复制
typedef struct {
    gpio_num_t gpio;
    bool active_high;
    bool current_state;
} led_control_t;
  • 作用:定义LED控制结构体
  • gpio_num_t gpio:存储GPIO引脚号
  • bool active_high:LED激活电平(true=高电平激活,false=低电平激活)
  • bool current_state:LED当前状态(true=开启,false=关闭)

LED初始化函数

代码语言:javascript
复制
void led_init(led_control_t *led, gpio_num_t gpio, bool active_high) {
  • 作用:LED控制结构体初始化函数
  • 参数
    • led_control_t *led:指向LED控制结构体的指针
    • gpio_num_t gpio:GPIO引脚号
    • bool active_high:LED激活电平
代码语言:javascript
复制
    led->gpio = gpio;
    led->active_high = active_high;
    led->current_state = false;
  • 作用:设置结构体成员变量
  • led->gpio = gpio:保存GPIO引脚号
  • led->active_high = active_high:保存激活电平设置
  • led->current_state = false:初始状态设为关闭
代码语言:javascript
复制
    // 配置GPIO
    gpio_config_t io_conf = {};
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = (1ULL << gpio);
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
  • 作用:配置GPIO参数
  • gpio_config_t io_conf = {}:创建GPIO配置结构体并初始化为0
  • io_conf.intr_type = GPIO_INTR_DISABLE:禁用GPIO中断
  • io_conf.mode = GPIO_MODE_OUTPUT:设置为输出模式
  • io_conf.pin_bit_mask = (1ULL << gpio):设置引脚位掩码,1ULL << gpio表示第gpio位为1
  • io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE:禁用下拉电阻
  • io_conf.pull_up_en = GPIO_PULLUP_DISABLE:禁用上拉电阻
代码语言:javascript
复制
    gpio_config(&io_conf);
  • 作用:应用GPIO配置
  • 用途:将配置参数应用到硬件
代码语言:javascript
复制
    // 初始状态为关闭
    gpio_set_level(gpio, active_high ? 0 : 1);
  • 作用:设置GPIO初始电平
  • 逻辑:如果LED是高电平激活,则输出低电平(关闭);如果LED是低电平激活,则输出高电平(关闭)
  • active_high ? 0 : 1:三元运算符,active_high为true时输出0,否则输出1
代码语言:javascript
复制
    ESP_LOGI(TAG, "LED control initialized on GPIO %d", gpio);
  • 作用:输出初始化完成日志
  • ESP_LOGI:信息级别日志输出函数
  • %d:格式化输出GPIO引脚号

LED开启函数

代码语言:javascript
复制
void led_turn_on(led_control_t *led) {
    gpio_set_level(led->gpio, led->active_high ? 1 : 0);
    led->current_state = true;
    ESP_LOGI(TAG, "LED turned ON");
}
  • 作用:开启LED
  • gpio_set_level(led->gpio, led->active_high ? 1 : 0)
    • 如果LED是高电平激活,输出高电平(1)
    • 如果LED是低电平激活,输出低电平(0)
  • led->current_state = true:更新状态为开启
  • ESP_LOGI(TAG, "LED turned ON"):输出开启日志

LED关闭函数

代码语言:javascript
复制
void led_turn_off(led_control_t *led) {
    gpio_set_level(led->gpio, led->active_high ? 0 : 1);
    led->current_state = false;
    ESP_LOGI(TAG, "LED turned OFF");
}
  • 作用:关闭LED
  • gpio_set_level(led->gpio, led->active_high ? 0 : 1)
    • 如果LED是高电平激活,输出低电平(0)
    • 如果LED是低电平激活,输出高电平(1)
  • led->current_state = false:更新状态为关闭
  • ESP_LOGI(TAG, "LED turned OFF"):输出关闭日志

LED切换函数

代码语言:javascript
复制
void led_toggle(led_control_t *led) {
    if (led->current_state) {
        led_turn_off(led);
    } else {
        led_turn_on(led);
    }
}
  • 作用:切换LED状态
  • 逻辑:如果当前是开启状态,则关闭;如果当前是关闭状态,则开启
  • if (led->current_state):检查当前状态
  • led_turn_off(led):调用关闭函数
  • led_turn_on(led):调用开启函数

LED状态设置函数

代码语言:javascript
复制
void led_set_state(led_control_t *led, bool state) {
    if (state) {
        led_turn_on(led);
    } else {
        led_turn_off(led);
    }
}
  • 作用:根据参数设置LED状态
  • 参数bool state- true表示开启,false表示关闭
  • 逻辑:根据state参数调用相应的开启或关闭函数

LED状态获取函数

代码语言:javascript
复制
bool led_get_state(led_control_t *led) {
    return led->current_state;
}
  • 作用:获取LED当前状态
  • 返回值:true表示开启,false表示关闭
  • 用途:用于查询LED的当前状态

主函数

代码语言:javascript
复制
void app_main(void) {
  • 作用:ESP32应用程序主入口函数
  • 特点:这是ESP-IDF框架要求的固定函数名,系统启动后会自动调用
代码语言:javascript
复制
    ESP_LOGI(TAG, "Starting LED control example");
  • 作用:输出程序启动日志
代码语言:javascript
复制
    // 创建LED控制对象
    led_control_t led;
    led_init(&led, GPIO_NUM_2, true);  // GPIO2, 高电平有效
  • 作用:创建LED控制结构体并初始化
  • led_control_t led:声明LED控制结构体变量
  • led_init(&led, GPIO_NUM_2, true):初始化LED控制,使用GPIO2,高电平激活
  • &led:传递结构体地址
  • GPIO_NUM_2:ESP32的GPIO2引脚
  • true:LED高电平激活
代码语言:javascript
复制
    // 测试LED功能
    ESP_LOGI(TAG, "Testing LED control...");
  • 作用:输出测试开始日志
代码语言:javascript
复制
    // 打开LED
    led_turn_on(&led);
    vTaskDelay(pdMS_TO_TICKS(1000));
  • 作用:开启LED并延时1秒
  • led_turn_on(&led):调用LED开启函数
  • vTaskDelay(pdMS_TO_TICKS(1000)):FreeRTOS延时函数,延时1000毫秒
代码语言:javascript
复制
    // 关闭LED
    led_turn_off(&led);
    vTaskDelay(pdMS_TO_TICKS(1000));
  • 作用:关闭LED并延时1秒
代码语言:javascript
复制
    // 切换LED状态
    led_toggle(&led);
    vTaskDelay(pdMS_TO_TICKS(1000));
  • 作用:切换LED状态并延时1秒
代码语言:javascript
复制
    // 设置LED状态
    led_set_state(&led, true);
    vTaskDelay(pdMS_TO_TICKS(1000));
  • 作用:设置LED为开启状态并延时1秒
代码语言:javascript
复制
    // 获取LED状态
    bool state = led_get_state(&led);
    ESP_LOGI(TAG, "Current LED state: %s", state ? "ON" : "OFF");
  • 作用:获取并显示LED当前状态
  • bool state = led_get_state(&led):获取LED状态
  • state ? "ON" : "OFF":三元运算符,根据状态显示"ON"或"OFF"
代码语言:javascript
复制
    // 循环闪烁
    ESP_LOGI(TAG, "Starting LED blink loop...");
    int count = 0;
    while (1) {
        led_toggle(&led);
        ESP_LOGI(TAG, "LED blink count: %d", count++);
        vTaskDelay(pdMS_TO_TICKS(500));
    }
  • 作用:进入无限循环,LED每500毫秒闪烁一次
  • int count = 0:初始化计数器
  • while (1):无限循环
  • led_toggle(&led):切换LED状态
  • count++:计数器递增(后置递增)
  • vTaskDelay(pdMS_TO_TICKS(500)):延时500毫秒
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-10-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 网罗开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 📚 本周学习目标
  • 🎯 第3课:C++ 基础与面向对象思维
    • 3.1 C vs C++:为什么这个工程用 C++
      • C 语言 vs C++ 语言对比
      • 为什么小智 AI 项目选择 C++?
      • 项目中的 C++ 特性应用
    • 3.2 类与对象、构造函数与析构函数
      • 类与对象基础
      • 构造函数详解
      • 析构函数详解
    • 3.3 单例模式在 Application 类中的使用
      • 单例模式基础
      • 单例模式的优势
      • 其他单例模式应用
    • 3.4 快速过一遍 STL
      • STL 容器介绍
      • STL 算法使用
      • 智能指针使用
    • 3.5 上机练习:写一个简单的类,封装 LED 开关
      • 实验目标
      • 实验步骤
      • 实验总结
    • 学习资源
  • 附加内容
    • 头文件包含部分
    • 全局变量定义
    • 数据结构定义
    • LED初始化函数
    • LED开启函数
    • LED关闭函数
    • LED切换函数
    • LED状态设置函数
    • LED状态获取函数
    • 主函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档