1. 标准模板库 (STL)
a. vector 动态数组
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 遍历vector
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 添加元素
numbers.push_back(6);
// 访问元素
std::cout << "First element: " << numbers[0] << std::endl;
return 0;
}
b. map 键值对
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> ageMap;
ageMap["Alice"] = 30;
ageMap["Bob"] = 25;
// 遍历map
for (const auto& pair : ageMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
// 查找元素
if (ageMap.find("Alice") != ageMap.end()) {
std::cout << "Alice's age: " << ageMap["Alice"] << std::endl;
}
return 0;
}
2. 模板
a. 函数模板
#include <iostream>
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << "int: " << add(3, 4) << std::endl;
std::cout << "double: " << add(3.5, 4.5) << std::endl;
return 0;
}
b. 类模板
#include <iostream>
template <typename T>
class Box {
public:
Box(T value) : value(value) {}
T getValue() { return value; }
private:
T value;
};
int main() {
Box<int> intBox(123);
Box<std::string> strBox("Hello");
std::cout << "intBox: " << intBox.getValue() << std::endl;
std::cout << "strBox: " << strBox.getValue() << std::endl;
return 0;
}
3. 继承和多态
a. 基本继承
#include <iostream>
class Animal {
public:
void eat() {
std::cout << "Animal is eating." << std::endl;
}
};
class Dog : public Animal {
public:
void bark() {
std::cout << "Dog is barking." << std::endl;
}
};
int main() {
Dog dog;
dog.eat(); // 继承自Animal
dog.bark();
return 0;
}
b. 多态
#include <iostream>
class Animal {
public:
virtual void makeSound() {
std::cout << "Some generic animal sound." << std::endl;
}
};
class Dog : public Animal {
public:
void makeSound() override {
std::cout << "Bark!" << std::endl;
}
};
class Cat : public Animal {
public:
void makeSound() override {
std::cout << "Meow!" << std::endl;
}
};
void playSound(Animal* animal) {
animal->makeSound();
}
int main() {
Dog dog;
Cat cat;
playSound(&dog); // 输出: Bark!
playSound(&cat); // 输出: Meow!
return 0;
}
4. 异常处理
#include <iostream>
int main() {
try {
int divisor = 0;
if (divisor == 0) {
throw std::runtime_error("除数不能为零");
}
int result = 10 / divisor;
std::cout << "Result: " << result << std::endl;
} catch (const std::exception& e) {
std::cerr << "捕获到异常: " << e.what() << std::endl;
}
return 0;
}
5. 智能指针
智能指针是C++11引入的,用于自动管理内存,避免内存泄漏。
a. unique_ptr 独占所有权的智能指针,不能共享。
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass() { std::cout << "构造函数" << std::endl; }
~MyClass() { std::cout << "析构函数" << std::endl; }
void display() { std::cout << "显示内容" << std::endl; }
};
int main() {
std::unique_ptr<MyClass> ptr1(new MyClass()); // 使用unique_ptr管理MyClass对象
ptr1->display();
if (!ptr1) {
std::cout << "ptr1现在为空" << std::endl;
} else {
std::cout << "ptr1现在不为空" << std::endl;
}
// std::unique_ptr<MyClass> ptr2 = ptr1; // 不能复制unique_ptr
std::cout << "使用move转移ptr1所有权" << std::endl;
std::unique_ptr<MyClass> ptr2 = std::move(ptr1); // 使用move转移所有权
if (!ptr1) {
std::cout << "ptr1现在为空" << std::endl;
}
ptr2->display();
return 0;
}
b. shared_ptr 共享所有权的智能指针,多个指针可以共同拥有资源。
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass() { std::cout << "构造函数" << std::endl; }
~MyClass() { std::cout << "析构函数" << std::endl; }
void display() { std::cout << "显示内容" << std::endl; }
};
int main() {
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
{
std::shared_ptr<MyClass> ptr2 = ptr1; // 共享所有权
ptr2->display();
std::cout << "ptr2 离开作用域" << std::endl;
}
std::cout << "ptr1仍然有效" << std::endl;
ptr1->display();
return 0;
}
c.weak_ptr用于解决循环引用问题,它不改变资源的引用计数。
#include <iostream>
#include <memory>
class Resource {
public:
std::weak_ptr<Resource> other;
Resource() { std::cout << "资源已分配" << std::endl; }
~Resource() { std::cout << "资源已释放" << std::endl; }
void print() { std::cout << "使用资源" << std::endl; }
};
int main() {
{
std::shared_ptr<Resource> res1 = std::make_shared<Resource>();
std::shared_ptr<Resource> res2 = std::make_shared<Resource>();
res1->other = res2;
res2->other = res1;
std::cout << "引用计数: " << res1.use_count() << std::endl; // 输出: 1
std::cout << "引用计数: " << res2.use_count() << std::endl; // 输出: 1
} // 资源自动释放
return 0;
}
6. Lambda表达式
Lambda表达式是C++11引入的一种用于定义匿名函数的简洁方法。
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用Lambda表达式打印元素
std::for_each(numbers.begin(), numbers.end(), [](int num) {
std::cout << num << " ";
});
std::cout << std::endl;
// 使用Lambda表达式计算平方
std::for_each(numbers.begin(), numbers.end(), [](int& num) {
num = num * num;
});
// 打印平方后的结果
std::for_each(numbers.begin(), numbers.end(), [](int num) {
std::cout << num << " ";
});
std::cout << std::endl;
return 0;
}
7. 文件操作
C++通过库进行文件操作。
#include <iostream>
#include <fstream>
#include <string>
int main() {
// 写入文件
std::ofstream outFile("example.txt");
if (outFile.is_open()) {
outFile << "这是一个例子文件。\n";
outFile << "包含多行文本。\n";
outFile.close();
} else {
std::cerr << "无法打开文件进行写入。" << std::endl;
}
// 读取文件
std::ifstream inFile("example.txt");
if (inFile.is_open()) {
std::string line;
while (getline(inFile, line)) {
std::cout << line << std::endl;
}
inFile.close();
} else {
std::cerr << "无法打开文件进行读取。" << std::endl;
}
return 0;
}
8. 多线程编程
C++11引入了多线程支持,可以使用库进行多线程编程。
#include <iostream>
#include <thread>
void printMessage(const std::string& message) {
std::cout << message << std::endl;
}
int main() {
std::thread t1(printMessage, "Hello from thread 1");
std::thread t2(printMessage, "Hello from thread 2");
// 等待线程完成
t1.join();
t2.join();
return 0;
}
9. C++11/14/17/20新特性
C++许多新特性,例如auto、nullptr、range-based for、constexpr、structured bindings等。
a. auto关键字
#include <iostream>
#include <vector>
int main() {
auto x = 5; // 编译器推断x为int
auto y = 3.14; // 编译器推断y为double
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (auto num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
b. nullptr关键字
#include <iostream>
void foo(int* ptr) {
if (ptr) {
std::cout << "指针非空" << std::endl;
} else {
std::cout << "指针为空" << std::endl;
}
}
int main() {
int* p = nullptr; // 使用nullptr初始化指针
foo(p);
return 0;
}
c. range-based for循环
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
d. constexpr关键字
#include <iostream>
constexpr int square(int x) {
return x * x;
}
int main() {
constexpr int result = square(5); // 编译时计算
std::cout << "Square of 5 is: " << result << std::endl;
return 0;
}
10. 命名空间
命名空间用于避免命名冲突
#include <iostream>
namespace first {
void display() {
std::cout << "第一命名空间" << std::endl;
}
}
namespace second {
void display() {
std::cout << "第二命名空间" << std::endl;
}
}
int main() {
first::display();
second::display();
return 0;
}
11. 运算符重载
运算符重载允许你为自定义类型定义新的运算行为。
#include <iostream>
class Complex {
public:
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
// 重载加法运算符
Complex operator + (const Complex& other) {
return Complex(real + other.real, imag + other.imag);
}
void display() {
std::cout << real << " + " << imag << "i" << std::endl;
}
private:
double real, imag;
};
int main() {
Complex c1(3.0, 4.0);
Complex c2(1.0, 2.0);
Complex c3 = c1 + c2;
c3.display();
return 0;
}
12. 标准库算法
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> numbers = {5, 3, 1, 4, 2};
// 排序
std::sort(numbers.begin(), numbers.end());
std::cout << "排序后: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 查找
auto it = std::find(numbers.begin(), numbers.end(), 3);
if (it != numbers.end()) {
std::cout << "找到数字 3" << std::endl;
} else {
std::cout << "未找到数字 3" << std::endl;
}
return 0;
}
13. 类型转换
#include <iostream>
int main() {
// static_cast
int a = 10;
double b = static_cast<double>(a);
std::cout << "static_cast: " << b << std::endl;
// const_cast
const int c = 20;
int* d = const_cast<int*>(&c);
*d = 30;
std::cout << "const_cast: " << c << std::endl; // 注意:修改const变量的行为是未定义的
return 0;
}
14. 动态内存管理
C++使用new和delete进行动态内存管理。
#include <iostream>
int main() {
// 动态分配一个整数
int* p = new int(10);
std::cout << "动态分配的整数: " << *p << std::endl;
delete p; // 释放内存
// 动态分配一个数组
int* arr = new int[5] {1, 2, 3, 4, 5};
std::cout << "动态分配的数组: ";
for (int i = 0; i < 5; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
delete[] arr; // 释放数组内存
return 0;
}
15. 函数对象
函数对象是一个重载了operator()的对象,可以像函数一样调用。
#include <iostream>
#include <vector>
#include <algorithm>
class Add {
public:
int operator()(int a, int b) {
return a + b;
}
};
int main() {
Add add;
int result = add(3, 4);
std::cout << "函数对象调用结果: " << result << std::endl;
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::for_each(numbers.begin(), numbers.end(), [](int &num) { num = num * 2; });
std::cout << "使用Lambda修改后的数组: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
16. 标准库容器
a. list 链表
#include <iostream>
#include <list>
int main() {
std::list<int> numbers = {1, 2, 3, 4, 5};
numbers.push_back(6);
numbers.push_front(0);
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
b. set 集合
#include <iostream>
#include <set>
int main() {
std::set<int> numbers = {1, 2, 3, 4, 5};
numbers.insert(6);
numbers.insert(3); // 重复插入无效
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
17. 友元函数和友元类
友元函数和友元类允许你访问类的私有成员。
a.友元函数
#include <iostream>
class Box {
private:
double width;
public:
Box(double w) : width(w) {}
friend void printWidth(Box box); // 友元函数声明
};
void printWidth(Box box) {
std::cout << "Box 宽度: " << box.width << std::endl; // 访问私有成员
}
int main() {
Box box(10.0);
printWidth(box);
return 0;
}
b.友元类
#include <iostream>
class ClassB; // 前向声明
class ClassA {
public:
void show(ClassB& b);
};
class ClassB {
private:
int b;
public:
ClassB(int val) : b(val) {}
friend class ClassA; // 声明 ClassA 为友元类
};
void ClassA::show(ClassB& b) {
std::cout << "ClassB 的私有成员 b: " << b.b << std::endl;
}
int main() {
ClassB objB(10);
ClassA objA;
objA.show(objB);
return 0;
}
18. 移动语义
C++11引入了移动语义,通过std::move和移动构造函数、移动赋值运算符实现高效的资源管理。
#include <iostream>
#include <utility>
class MyClass {
public:
int* data;
// 构造函数
MyClass(int value) : data(new int(value)) {
std::cout << "构造函数: 分配资源" << std::endl;
}
// 移动构造函数
MyClass(MyClass&& other) noexcept : data(other.data) {
other.data = nullptr;
std::cout << "移动构造函数: 转移资源" << std::endl;
}
// 移动赋值运算符
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
delete data; // 释放当前资源
data = other.data; // 转移资源
other.data = nullptr;
std::cout << "移动赋值运算符: 转移资源" << std::endl;
}
return *this;
}
// 析构函数
~MyClass() {
delete data;
std::cout << "析构函数: 释放资源" << std::endl;
}
};
int main() {
MyClass obj1(10);
MyClass obj2 = std::move(obj1); // 调用移动构造函数
return 0;
}
19.混合编程(C++与其他语言结合)
C++可以与其他编程语言结合使用,通常是通过外部库或语言绑定。
#include <iostream>
extern "C" {
#include <math.h> // 使用C语言的math库
}
int main() {
double result = sqrt(16.0); // 调用C库函数
std::cout << "sqrt(16.0) = " << result << std::endl;
return 0;
}
20.工厂模式
工厂模式用于创建对象的接口,使得子类可以决定实例化哪一个类。
#include <iostream>
#include <memory>
// 产品接口
class Product {
public:
virtual ~Product() = default;
virtual void use() = 0;
};
// 具体产品A
class ConcreteProductA : public Product {
public:
void use() override {
std::cout << "使用产品A" << std::endl;
}
};
// 具体产品B
class ConcreteProductB : public Product {
public:
void use() override {
std::cout << "使用产品B" << std::endl;
}
};
// 工厂接口
class Factory {
public:
virtual ~Factory() = default;
virtual std::unique_ptr<Product> createProduct() = 0;
};
// 具体工厂A
class ConcreteFactoryA : public Factory {
public:
std::unique_ptr<Product> createProduct() override {
return std::make_unique<ConcreteProductA>();
}
};
// 具体工厂B
class ConcreteFactoryB : public Factory {
public:
std::unique_ptr<Product> createProduct() override {
return std::make_unique<ConcreteProductB>();
}
};
int main() {
std::unique_ptr<Factory> factoryA = std::make_unique<ConcreteFactoryA>();
std::unique_ptr<Factory> factoryB = std::make_unique<ConcreteFactoryB>();
std::unique_ptr<Product> productA = factoryA->createProduct();
std::unique_ptr<Product> productB = factoryB->createProduct();
productA->use(); // 输出: 使用产品A
productB->use(); // 输出: 使用产品B
return 0;
}