C++学习

C++ 学习指南:核心概念与实践应用

C++ 是一种功能强大且广泛应用的编程语言,尤其适合系统开发、游戏引擎、高性能计算等领域。下面将从核心语法到高级特性,结合实际案例进行讲解。

1. C++ 基础语法与核心概念

C++ 是一种静态类型、编译式语言,支持面向过程、面向对象和泛型编程范式。

基础语法示例:

cpp

#include <iostream>  // 输入输出流库

int main() {
    // 变量声明与初始化
    int num = 42;
    double pi = 3.14;
    std::string name = "Doubao";  // C++11 标准引入的字符串类

    // 条件语句
    if (num > 10) {
        std::cout << "Number is greater than 10." << std::endl;
    }

    // 循环语句
    for (int i = 0; i < 5; i++) {
        std::cout << "Iteration: " << i << std::endl;
    }

    return 0;
}

2. 面向对象编程(OOP)

C++ 的核心优势之一是支持面向对象编程,包括类、继承、多态等特性。

类与对象示例:

cpp

class Shape {
protected:
    std::string name;

public:
    // 构造函数
    Shape(const std::string& n) : name(n) {}

    // 虚函数(用于多态)
    virtual double area() const = 0;  // 纯虚函数,使 Shape 成为抽象类

    // 普通成员函数
    void printName() const {
        std::cout << "Shape: " << name << std::endl;
    }
};

// 派生类:圆形
class Circle : public Shape {
private:
    double radius;

public:
    Circle(double r) : Shape("Circle"), radius(r) {}

    // 实现基类的纯虚函数
    double area() const override {
        return 3.14 * radius * radius;
    }
};

// 派生类:矩形
class Rectangle : public Shape {
private:
    double width, height;

public:
    Rectangle(double w, double h) : Shape("Rectangle"), width(w), height(h) {}

    double area() const override {
        return width * height;
    }
};
3. 多态(Polymorphism)

多态允许通过基类指针或引用调用派生类的方法,实现运行时绑定。

多态示例:

cpp

void printArea(const Shape& shape) {
    shape.printName();
    std::cout << "Area: " << shape.area() << std::endl;  // 动态绑定到派生类的 area()
}

int main() {
    Circle circle(5.0);
    Rectangle rect(4.0, 6.0);

    printArea(circle);   // 输出:Circle, Area: 78.5
    printArea(rect);     // 输出:Rectangle, Area: 24.0

    return 0;
}
4. 工厂模式(Factory Pattern)

工厂模式是一种创建对象的设计模式,将对象的创建逻辑封装在一个工厂类中。

简单工厂示例:

cpp

class ShapeFactory {
public:
    static Shape* createShape(const std::string& type) {
        if (type == "circle") {
            return new Circle(5.0);
        } else if (type == "rectangle") {
            return new Rectangle(4.0, 6.0);
        }
        return nullptr;  // 无效类型返回 nullptr
    }
};

// 使用工厂创建对象
int main() {
    Shape* circle = ShapeFactory::createShape("circle");
    Shape* rect = ShapeFactory::createShape("rectangle");

    if (circle) printArea(*circle);
    if (rect) printArea(*rect);

    delete circle;  // 记得释放动态分配的内存
    delete rect;

    return 0;
}
5. static 和 const 的用法
static 关键字:
  • 静态变量:在类中声明的静态变量为所有对象共享,类外初始化。
  • 静态函数:不依赖于对象,只能访问静态成员。

cpp

class Counter {
private:
    static int count;  // 静态成员变量声明

public:
    static int getCount() {  // 静态成员函数
        return count;
    }

    void increment() {
        count++;  // 所有对象共享 count
    }
};

// 静态成员变量必须在类外初始化
int Counter::count = 0;
const 关键字:
  • 常量变量:值不可修改。
  • 常量成员函数:不修改对象状态。
  • 常量对象:只能调用常量成员函数。

cpp

class Example {
private:
    const int value;  // 常量成员变量
    int data;

public:
    Example(int v, int d) : value(v), data(d) {}  // 必须在初始化列表中初始化常量成员

    // 常量成员函数(不修改对象状态)
    int getData() const {
        return data;
    }

    // 非常量成员函数
    void setData(int d) {
        data = d;
    }
};

// 常量对象只能调用常量成员函数
const Example obj(10, 20);
obj.getData();  // 合法
// obj.setData(30);  // 非法:常量对象不能调用非常量函数
1. 对象构造函数详解

C++ 提供了多种构造函数类型,用于对象的初始化。

示例代码:

cpp

class Point {
private:
    int x, y;

public:
    // 默认构造函数
    Point() : x(0), y(0) {}

    // 带参数的构造函数
    Point(int xVal, int yVal) : x(xVal), y(yVal) {}

    // 拷贝构造函数
    Point(const Point& other) : x(other.x), y(other.y) {
        std::cout << "Copy constructor called" << std::endl;
    }

    // 移动构造函数(C++11)
    Point(Point&& other) noexcept : x(other.x), y(other.y) {
        other.x = 0;
        other.y = 0;
        std::cout << "Move constructor called" << std::endl;
    }

    // 拷贝赋值运算符
    Point& operator=(const Point& other) {
        if (this != &other) {
            x = other.x;
            y = other.y;
        }
        std::cout << "Copy assignment called" << std::endl;
        return *this;
    }

    // 移动赋值运算符(C++11)
    Point& operator=(Point&& other) noexcept {
        if (this != &other) {
            x = other.x;
            y = other.y;
            other.x = 0;
            other.y = 0;
        }
        std::cout << "Move assignment called" << std::endl;
        return *this;
    }

    // 析构函数
    ~Point() {
        // 清理资源(如动态内存、文件句柄等)
    }
};

// 使用示例
int main() {
    Point p1;                 // 默认构造
    Point p2(3, 4);           // 带参构造
    Point p3 = p2;            // 拷贝构造
    p1 = p3;                  // 拷贝赋值
    Point p4 = std::move(p1); // 移动构造
    p2 = std::move(p3);       // 移动赋值
    return 0;
}

2. Lambda 表达式(C++11 起)

Lambda 表达式是一种匿名函数对象,用于创建临时函数。

基本语法:

cpp

[capture list](parameter list) -> return type { function body }

示例代码:

cpp

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // 1. 无捕获,无参数,返回值自动推导
    auto greet = [] { std::cout << "Hello, Lambda!" << std::endl; };
    greet(); // 输出: Hello, Lambda!

    // 2. 捕获外部变量 by value
    int x = 10;
    auto add_x = [x](int a) { return a + x; };
    std::cout << add_x(5) << std::endl; // 输出: 15

    // 3. 捕获外部变量 by reference
    auto increment = [&x] { x++; };
    increment();
    std::cout << x << std::endl; // 输出: 11

    // 4. 通用捕获(C++14)
    auto y = 20;
    auto capture_all = [=, &y](int a) { return a + x + y; };
    std::cout << capture_all(5) << std::endl; // 输出: 36

    // 5. 在算法中使用 lambda
    std::vector<int> nums = {1, 2, 3, 4, 5};
    std::for_each(nums.begin(), nums.end(), [](int num) {
        std::cout << num * 2 << " ";
    }); // 输出: 2 4 6 8 10

    // 6. 带 mutable 的 lambda
    auto modify_captured = [x]() mutable { x++; std::cout << x << std::endl; };
    modify_captured(); // 输出: 11(修改的是副本)
    std::cout << x << std::endl; // 输出: 10(原 x 未改变)

    return 0;
}
3. 智能指针(C++11 起)

智能指针自动管理内存,避免内存泄漏。

示例代码:

cpp

#include <memory>

class Resource {
public:
    Resource() { std::cout << "Resource acquired" << std::endl; }
    ~Resource() { std::cout << "Resource released" << std::endl; }
    void use() { std::cout << "Resource in use" << std::endl; }
};

int main() {
    // 1. unique_ptr:独占所有权
    std::unique_ptr<Resource> res1 = std::make_unique<Resource>();
    res1->use();
    // std::unique_ptr<Resource> res2 = res1; // 错误:不能拷贝
    std::unique_ptr<Resource> res2 = std::move(res1); // 正确:只能移动

    // 2. shared_ptr:共享所有权(引用计数)
    std::shared_ptr<Resource> res3 = std::make_shared<Resource>();
    {
        std::shared_ptr<Resource> res4 = res3;
        std::cout << "Use count: " << res3.use_count() << std::endl; // 输出: 2
    } // res4 析构,引用计数减1
    std::cout << "Use count: " << res3.use_count() << std::endl; // 输出: 1

    // 3. weak_ptr:弱引用,不增加引用计数
    std::shared_ptr<int> shared = std::make_shared<int>(42);
    std::weak_ptr<int> weak = shared;
    std::cout << "Weak use count: " << weak.use_count() << std::endl; // 输出: 1

    if (auto locked = weak.lock()) { // 检查对象是否还存在
        std::cout << *locked << std::endl; // 输出: 42
    }

    return 0;
} // res2、res3、shared 析构,资源释放
4. 模板(Templates)

模板允许创建通用的函数和类,支持泛型编程。

函数模板示例:

cpp

// 交换任意类型的两个值
template <typename T>
void swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

// 使用示例
int x = 5, y = 10;
swap(x, y); // 自动推导 T 为 int

double a = 3.14, b = 2.71;
swap(a, b); // 自动推导 T 为 double

类模板示例:

cpp

// 通用的 Pair 类
template <typename T1, typename T2>
class Pair {
private:
    T1 first;
    T2 second;

public:
    Pair(const T1& a, const T2& b) : first(a), second(b) {}
    T1 getFirst() const { return first; }
    T2 getSecond() const { return second; }
};

// 使用示例
Pair<int, std::string> p(42, "Doubao");
std::cout << p.getFirst() << ", " << p.getSecond() << std::endl;
5. 右值引用与移动语义(C++11 起)

右值引用允许捕获临时对象(右值),实现资源的高效转移。

示例代码:

cpp

#include <iostream>
#include <vector>

class BigArray {
private:
    int* data;
    size_t size;

public:
    // 构造函数
    BigArray(size_t s) : size(s), data(new int[s]) {
        std::cout << "Constructor: Allocated " << size << " elements" << std::endl;
    }

    // 拷贝构造函数
    BigArray(const BigArray& other) : size(other.size), data(new int[other.size]) {
        std::cout << "Copy Constructor: Allocated and copied " << size << " elements" << std::endl;
        for (size_t i = 0; i < size; ++i) {
            data[i] = other.data[i];
        }
    }

    // 移动构造函数
    BigArray(BigArray&& other) noexcept : data(other.data), size(other.size) {
        std::cout << "Move Constructor: Transferred ownership of " << size << " elements" << std::endl;
        other.data = nullptr; // 防止 other 析构时删除内存
        other.size = 0;
    }

    // 析构函数
    ~BigArray() {
        delete[] data;
    }
};

// 使用示例
BigArray createArray(size_t size) {
    return BigArray(size); // 返回临时对象(右值)
}

int main() {
    // 拷贝构造(效率低)
    BigArray arr1(1000);
    BigArray arr2(arr1); // 调用拷贝构造函数

    // 移动构造(高效)
    BigArray arr3 = createArray(1000); // 调用移动构造函数
    return 0;
}
6. 现代 C++ 特性(C++14/17/20)
  • C++14 特性:

    cpp

    // 泛型 lambda(C++14)
    auto add = [](auto a, auto b) { return a + b; };
    std::cout << add(3, 4) << std::endl;      // 输出: 7
    std::cout << add(3.14, 2.71) << std::endl; // 输出: 5.85
    
    // 返回类型推导(C++14)
    auto calculate() { return 3.14 * 2; }
    
  • C++17 特性:

    cpp

    // 结构化绑定(Structured Binding)
    std::pair<int, std::string> getPair() { return {42, "Doubao"}; }
    auto [num, str] = getPair(); // 直接解包 pair/tuple
    
    // if constexpr(编译时条件判断)
    template <typename T>
    auto getValue(T t) {
        if constexpr (std::is_integral_v<T>) {
            return t * 2;
        } else {
            return t;
        }
    }
    
  • C++20 特性:

    cpp

    // 概念(Concepts)
    template <typename T>
    requires std::integral<T>
    T add(T a, T b) { return a + b; }
    
    // 范围(Ranges)
    std::vector<int> nums = {1, 2, 3, 4, 5};
    auto squared = nums | std::views::transform([](int x) { return x * x; });
    
7. 异常处理

cpp

class DivideByZeroException : public std::exception {
public:
    const char* what() const noexcept override {
        return "Division by zero!";
    }
};

double divide(double a, double b) {
    if (b == 0) {
        throw DivideByZeroException(); // 抛出异常
    }
    return a / b;
}

int main() {
    try {
        double result = divide(10.0, 0.0);
        std::cout << "Result: " << result << std::endl;
    } catch (const DivideByZeroException& e) {
        std::cerr << "Error: " << e.what() << std::endl; // 捕获并处理异常
    } catch (...) {
        std::cerr << "Unknown exception occurred!" << std::endl;
    }
    return 0;
}
8. 多线程编程(C++11 起)

cpp

#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; }); // 等待主线程通知
    std::cout << "Worker thread is working!" << std::endl;
}

int main() {
    std::thread t(worker);

    // 做一些准备工作
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one(); // 通知工作线程

    t.join(); // 等待线程完成
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值