CPP(一)概述1.1

编程范式

编程范式(Programming Paradigms)是指导我们如何组织代码、设计程序结构的一种“思维方式”或“风格体系”。不同范式之间的差异,往往体现在:

  • 程序的组织结构(如模块、函数、对象)

  • 状态的管理方式(如变量是否可变)

  • 控制流的表达方式(如循环 vs 递归)

主流范式

1. 命令式编程

✨思想:

直接告诉计算机“怎么做”,一步一步地描述操作流程。

✅特点:

  • 程序包含语句(statements)和可变变量(mutable variables)

  • 强调状态的改变

  • 控制流使用:顺序、选择(if)、循环(for/while)

计算 1 到 100 的和
#include <iostream>

int main() {
    int sum = 0;                    // 声明一个整数变量 sum,用来保存累加结果
    for (int i = 1; i <= 100; ++i) {// 使用 for 循环,从 1 加到 100
        sum += i;                   // 每次循环将当前 i 加入到 sum
    }
    std::cout << "Sum = " << sum << std::endl; // 打印总和
    return 0;
}

2. 结构化编程

✨思想:

命令式的子集,强调使用结构化控制流(非goto),提高程序可读性与可维护性。

✅特点:

  • 使用子程序(函数)组织代码

  • 禁用goto,使用 if/else、while、for 等结构

  • 更强调代码块结构和嵌套层级

    递归计算阶乘
    #include <iostream>
    
    // 递归函数:用于计算 n 的阶乘
    int factorial(int n) {
        if (n == 0) return 1;       // 阶乘的边界条件:0! = 1
        else return n * factorial(n - 1); // 递归定义:n! = n * (n - 1)!
    }
    
    int main() {
        int number = 5;
        int result = factorial(number); // 调用函数计算 5!
        std::cout << number << "! = " << result << std::endl;
        return 0;
    }
    

3. 面向对象编程

✨思想:

通过“对象和类”模拟现实世界,将数据和行为打包在一起,强调封装、继承、多态

✅特点:

  • 封装:隐藏内部实现,只暴露接口

  • 继承:通过基类派生子类,重用逻辑

  • 多态:通过接口/虚函数实现运行时动态行为

    动物叫声模拟
    #include <iostream>
    using namespace std;
    
    // 基类:Animal,提供公共接口
    class Animal {
    public:
        virtual void speak() { // 虚函数:允许子类重写,实现多态
            cout << "Some animal sound\n";
        }
    };
    
    // 派生类:Dog
    class Dog : public Animal {
    public:
        void speak() override { // 重写基类方法
            cout << "Woof! Woof!\n";
        }
    };
    
    // 派生类:Cat
    class Cat : public Animal {
    public:
        void speak() override {
            cout << "Meow~\n";
        }
    };
    
    // 多态调用函数
    void makeSound(Animal* a) {
        a->speak(); // 根据对象类型调用对应的 speak 方法
    }
    
    int main() {
        Dog d;
        Cat c;
        makeSound(&d); // 输出:Woof! Woof!
        makeSound(&c); // 输出:Meow~
        return 0;
    }
    

4. 函数式编程

✨思想:

告诉计算机“做什么”,而不是怎么做。函数是第一等公民,没有副作用,强调不可变性。

✅特点:

  • 不可变变量(immutable)

  • 无副作用的纯函数(pure function)

  • 使用递归代替循环

  • 常用高阶函数(如 map, reduce)

    平方所有数组元素
    #include <iotream>
    #include <vector>
    #include <ranges> // C++20 ranges
    
    int main() {
        std::vector<int> nums{1, 2, 3, 4, 5};
    
        // 使用 ranges 的 transform 视图将每个元素平方(函数式写法)
        auto squares = nums | std::ranges::views::transform([](int x) {
            return x * x; // lambda 表达式,返回输入的平方
        });
    
        // 打印结果
        for (int n : squares) {
            std::cout << n << " "; // 输出:1 4 9 16 25
        }
        std::cout << std::endl;
        return 0;
    }
    

5. 声明式编程

✨思想:

不描述怎么做,只描述做什么,由底层系统去实现执行细节。

✅特点:

  • 更接近人类逻辑描述

  • 状态抽象、控制流抽象

  • SQL、正则表达式、HTML 都是声明式的典型例子

    C++中使用 STL 算法(声明式风格)
    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    int main() {
        std::vector<int> data{1, 2, 3, 4, 5};
    
        // 使用 count_if 声明“我要统计偶数”,而不是手动写循环
        int even_count = std::count_if(data.begin(), data.end(), [](int x) {
            return x % 2 == 0; // 条件:x 是偶数
        });
    
        std::cout << "Even numbers count: " << even_count << std::endl; // 输出:2
        return 0;
    }
    

6. 事件驱动编程

✨思想:

程序执行依赖于事件(如用户输入、定时器、网络响应),事件监听和响应机制是核心。

✅特点:

  • 常用于GUI、嵌入式、游戏开发

  • 回调函数/事件循环为主要结构

7. 并发 / 并行编程

✨思想:

程序由多个“独立的执行流”组成,可能并行执行以提高效率。

✅特点:

  • 多线程、多进程、协程

  • 锁、互斥、信号量、线程池等同步机制

    两个线程并行打印信息
    #include <iostream>
    #include <thread> // 引入线程库
    
    // 子线程函数
    void printFromThread() {
        std::cout << "Hello from thread!\n";
    }
    
    int main() {
        // 创建并启动线程,执行函数 printFromThread
        std::thread t(printFromThread);
    
        // 主线程继续执行
        std::cout << "Hello from main!\n";
    
        // 等待子线程执行完毕
        t.join(); // 没有这句主线程可能提前结束
    
        return 0;
    }
    

面向对象编程

在介绍面向对象之前,先回顾一下面向过程

面向过程编程

✅ 定义

面向过程是一种以过程(即函数)为核心的编程方式。它强调的是“先定义好步骤”,然后将数据传入函数处理。

程序 = 数据结构 + 算法

  • 数据结构:如结构体、数组等

  • 算法(过程):一组函数、子程序,用来处理数据结构

 特征:

  • 函数是代码的基本组织单位

  • 数据是独立的,函数在处理时传入数据

  • 逻辑上是从上往下执行的流程

    #include <iostream>
    #include <string>
    
    // 数据结构
    struct Student {
        std::string name;
        int score;
    };
    
    // 操作函数
    void printStudent(const Student& s) {
        std::cout << "Name: " << s.name << ", Score: " << s.score << std::endl;
    }
    
    void updateScore(Student& s, int newScore) {
        s.score = newScore;
    }
    
    int main() {
        Student s = {"Alice", 85};   // 创建一个学生对象
        printStudent(s);             // 打印信息
        updateScore(s, 95);          // 修改分数
        printStudent(s);             // 再次打印
        return 0;
    }
    

    面向对象编程

    ✅ 定义:

    OOP 是一种以对象为核心的编程范式,对象将数据与操作数据的行为封装在一起

对象 = 数据结构 + 算法  
程序 = 一组对象 + 对象之间的交互(通信)

特征:

  • 封装:数据和方法封装在对象中

  • 继承:子类可以继承父类的属性和行为

  • 多态:通过虚函数实现接口调用的多样性

  • 数据和函数绑定在类内部

#include <iostream>
#include <string>

// 类定义
class Student {
private:
    std::string name;
    int score;

public:
    // 构造函数
    Student(std::string n, int s) : name(n), score(s) {}

    // 成员函数:打印信息
    void printInfo() const {
        std::cout << "Name: " << name << ", Score: " << score << std::endl;
    }

    // 成员函数:更新分数
    void setScore(int s) {
        score = s;
    }
};

int main() {
    Student s("Bob", 90); // 创建对象,封装了数据与方法
    s.printInfo();        // 对象内部方法访问数据
    s.setScore(100);      // 修改分数
    s.printInfo();        // 再次打印
    return 0;
}
对比维度面向过程面向对象
设计核心函数(操作)优先对象(数据+行为)优先
数据与函数关系分离,数据被函数操作封装在类中,对象自己管理自己的数据
组织结构函数 + 全局变量类 + 对象
扩展性修改已有函数可继承、重写,扩展性好
复用性以函数为单位复用以类和对象为单位复用
适用场景简单流程控制、嵌入式开发复杂系统、图形界面、游戏、业务系统
角度面向过程面向对象
比喻操作流水线工厂:一批原料逐步加工协作社会:每个对象各司其职相互通信
控制方式程序主控一切,调度函数对象主动响应调用,程序结构松耦合
管理数据通过函数传参/访问全局变量对象内封装数据,外部通过接口调用

 面向对象编程的三大优势

优势含义说明
重用性已编写好的类/模块可以被多个项目/类复用,避免重复开发。
灵活性通过组合、继承、重写等方式对已有模块重新“拼装”,适应不同需求。
扩展性对系统新增功能时,可以新增类/重写方法,而不是改动旧代码,符合开闭原则。


 三大特性

 一、封装(Encapsulation)

📌 概念:

封装是指将数据和对数据的操作方法组织到一个类中,并隐藏内部实现细节,外部通过接口访问数据。

✅ 优势:

  • 限制外部访问,保证数据安全

  • 提高模块化程度,使程序更易维护和扩展

#include <iostream>
#include <string>

// 封装:定义类 Student,把数据和操作封装在内部
class Student {
private:
    std::string name; // 私有成员变量:外部无法直接访问
    int score;

public:
    // 构造函数(初始化对象)
    Student(std::string n, int s) : name(n), score(s) {}

    // 公共接口:获取名字
    std::string getName() const {
        return name; // 通过接口获取私有数据
    }

    // 公共接口:设置成绩(带范围检查)
    void setScore(int s) {
        if (s >= 0 && s <= 100)
            score = s;
        else
            std::cout << "Invalid score!\n";
    }

    // 打印信息
    void printInfo() const {
        std::cout << "Name: " << name << ", Score: " << score << std::endl;
    }
};

int main() {
    Student stu("Alice", 90);   // 创建对象
    stu.printInfo();            // 访问公共方法
    stu.setScore(110);          // 设置非法成绩,被封装逻辑拒绝
    stu.setScore(95);           // 设置正确成绩
    stu.printInfo();
    return 0;
}

封装实现了“接口与实现分离”:我们不需要知道 score 是怎么存的、是否合法判断的,只要会用 setScore() 即可。

👨‍👧‍👦 二、继承

📌 概念:

继承是指子类自动拥有父类的成员(变量和函数),并可以扩展或重写这些成员,从而实现代码的复用和功能拓展。

✅ 优势:

  • 代码重用,提高开发效率

  • 子类可以在不修改父类的前提下添加或更改功能(符合开闭原则)

#include <iostream>
using namespace std;

// 父类(基类):动物
class Animal {
public:
    void breathe() {
        cout << "Animal breathing...\n";
    }

    // 虚函数:让子类实现自己的说话方式
    virtual void speak() {
        cout << "Animal sound...\n";
    }
};

// 子类:狗,继承自动获得 breathe 方法,并重写 speak
class Dog : public Animal {
public:
    void speak() override {
        cout << "Woof! Woof!\n";
    }

    void fetch() {
        cout << "Dog fetching the ball!\n";
    }
};

int main() {
    Dog d;
    d.breathe();  // 继承来的方法
    d.speak();    // 重写的方法
    d.fetch();    // 子类特有方法
    return 0;
}

🔍继承实现了代码复用:Dog 不需要重新实现 breathe(),可以直接用父类的。

🌀 三、多态

📌 概念:

多态允许不同的类对象对同一个方法调用作出不同响应。最常用于虚函数 + 基类指针/引用

✅ 优势:

  • 解耦调用者与实现者

  • 可以对一组类的对象进行统一操作,提高可扩展性

    #include <iostream>
    using namespace std;
    
    // 抽象基类:动物
    class Animal {
    public:
        virtual void speak() { // 虚函数:声明接口
            cout << "Animal sound...\n";
        }
    };
    
    // 子类:猫
    class Cat : public Animal {
    public:
        void speak() override {
            cout << "Meow~\n";
        }
    };
    
    // 子类:狗
    class Dog : public Animal {
    public:
        void speak() override {
            cout << "Woof!\n";
        }
    };
    
    // 接收基类指针的函数,表现出多态行为
    void makeSound(Animal* a) {
        a->speak(); // 实际调用哪个 speak 取决于传入对象类型
    }
    
    int main() {
        Cat c;
        Dog d;
        makeSound(&c); // 输出:Meow~
        makeSound(&d); // 输出:Woof!
        return 0;
    }
    

    泛型编程

泛型编程是一种编程范式,目标是编写与类型无关的算法和数据结构,以提高代码的通用性和重用性。

✅ 目的:

用统一的代码逻辑,处理多种不同的数据类型,而不必为每种类型编写重复的代码。

 举个栗子🌰

以前我们写函数时,只能固定类型,比如:

int max(int a, int b) {
    return a > b ? a : b;
}

但如果想比较两个 float 呢?还要写:

float max(float a, float b) { ... }

➡ 泛型编程就让我们写一个函数,可以比较任意类型:

template<typename T>
T max(T a, T b) {
    return a > b ? a : b;
}

🌟 这就是“把类型抽象为参数”的过程,即“参数化类型”。

 C++ 支持泛型的机制:模板

📌 模板的作用:

模板把类型数值参数化,不再在代码中写死,而是等“使用时”再指定

 两种模板:

模板类型用途语法示例
函数模板用于编写通用算法函数template<typename T> T func(...)
类模板用于编写通用数据结构template<typename T> class MyClass {}

函数模板

#include <iostream>
using namespace std;

// 函数模板:用于比较任意类型的两个值,返回较大的一个
template<typename T>        // T 是类型参数,占位
T myMax(T a, T b) {
    return (a > b) ? a : b; // 使用传入类型的 > 运算符
}

int main() {
    cout << myMax(3, 7) << endl;           // int
    cout << myMax(3.14, 2.72) << endl;     // double
    cout << myMax('a', 'z') << endl;       // char(按ASCII比较)
    return 0;
}

🔍 使用时,编译器会自动根据实参类型“实例化”为具体函数,例如 myMax<int>myMax<double> 等。

 类模板

#include <iostream>
using namespace std;

// 类模板:定义一个通用的容器,只存储一个元素
template<typename T>
class Box {
private:
    T value; // 成员变量:类型是模板参数 T
public:
    void set(const T& v) {
        value = v;
    }

    T get() const {
        return value;
    }
};

int main() {
    Box<int> intBox;          // 创建一个 int 类型的 Box
    intBox.set(42);
    cout << "intBox: " << intBox.get() << endl;

    Box<string> strBox;       // 创建一个 string 类型的 Box
    strBox.set("Hello");
    cout << "strBox: " << strBox.get() << endl;

    return 0;
}

STL

STL 六大组件

组件名称作用说明实质
容器 Containers存储数据的模板类(如数组、链表、集合等)模板类
迭代器 Iterators访问容器元素的“抽象指针”运算符重载类
算法 Algorithms对容器数据执行操作,如排序、查找、遍历模板函数
配接器 Adapters修改容器/函数/迭代器行为的包装器模板类
仿函数 Functors可像函数一样调用的对象,通常是函数对象或重载 () 的类类对象
分配器 Allocators控制容器底层内存分配策略模板类

 ① 容器

STL 容器是一些预定义的数据结构模板类,用于存储任意类型的数据,常见结构有:数组、链表、队列、集合、哈希表等。特殊的数据结构,实现了数组、 链表、队列等,实质是模板类

常用容器分类

序列式容器描述
vector<T>动态数组(常用)
list<T>双向链表
deque<T>双端队列

关联式容器描述
set<T>集合(自动排序)
map<K,V>键值对映射(自动排序)
unordered_map哈希表映射(无序)
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v = {1, 2, 3};  // 动态数组容器
    v.push_back(4);            // 插入元素
    for (int n : v)
        cout << n << " ";      // 输出:1 2 3 4
    return 0;
}

② 迭代器

迭代器是 STL 的“桥梁”,用于访问容器中的元素,一种复杂的指针,可以通过其读写容器中的对象,实质是运 算符重载

常见操作:

  • it++ / ++it:向后移动

  • *it:访问元素值

  • begin() / end():首尾迭代器

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> v = {10, 20, 30};
    vector<int>::iterator it;

    for (it = v.begin(); it != v.end(); ++it) {
        cout << *it << " ";  // 输出元素值
    }
    return 0;
}

③ 算法

STL 提供了大量的通用算法(排序、查找、复制、替换、变换、合并等),使用 模板函数 实现,支持任意容器,只要提供迭代器。读写容器对象的逻辑算法:排 序、遍历、查找、等等,实质 是模板函数

常用算法函数:

类别例子
排序sort(begin, end)
查找find(begin, end, value)
遍历for_each(begin, end, func)
统计count(begin, end, value)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> v = {5, 2, 9, 1};
    sort(v.begin(), v.end());  // 升序排序
    for (int n : v) cout << n << " "; // 输出:1 2 5 9
    return 0;
}

④ 配接器

配接器是 包装器类,用于改造已有容器或函数接口,实现更特化的行为。用来修饰容器、仿函数、迭代器接口

容器适配器:

适配器基础容器行为特化
stack<T>deque<T>栈(先进后出)
queue<T>deque<T>队列(先进先出)
priority_queue<T>vector<T>优先队列(最大堆)

⑤ 仿函数

仿函数是一个重载了 () 运算符的类对象,可像函数一样使用,常用作 算法参数。类似函数,通过重载()运算符来模拟函数行为的类.

作用:

  • 代替函数指针传入算法

  • 提供带状态的调用对象

  • 与 STL 算法结合使用灵活高效

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 仿函数:用于排序时的自定义比较器(按降序)
struct Greater {
    bool operator()(int a, int b) {
        return a > b;
    }
};

int main() {
    vector<int> v = {3, 1, 4};
    sort(v.begin(), v.end(), Greater()); // 使用仿函数
    for (int n : v) cout << n << " ";    // 输出:4 3 1
    return 0;
}

⑥ 空间配置器

分配器是 STL 中管理内存分配策略的机制(容器的空间配置管理的模板类),默认使用 std::allocator<T>,也可自定义实现内存池、对齐分配等策略。

  • 分离数据结构与内存管理逻辑

  • 提供统一的分配/释放接口

  • 用于提高内存效率或控制行为(如嵌入式、游戏)

#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> v; // 默认使用 allocator<int>
    v.push_back(1);
    v.push_back(2);
    cout << "Capacity: " << v.capacity() << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值