前言
大家好啊!今天咱们来聊聊C++这门既强大又"倔强"的语言。有人说C++是把双刃剑,用得好能削铁如泥,用不好可能把自己削了。哈哈,确实如此!但只要掌握了正确的学习路线,这把"剑"绝对能成为你职业生涯中的一大利器。
一、基础入门知识
C++的入门就像学做菜,先得认识各种食材和基本工具,才能烹饪出美味佳肴。
1. 数据类型与变量
C++的基本数据类型包括整型(int)、浮点型(float, double)、字符型(char)和布尔型(bool)。想象一下,这些类型就像不同的容器,有的适合装整数,有的适合装小数。
int age = 28; // 整型,就像一个只能装整数的盒子
double salary = 10000.5; // 双精度浮点型,可以装带小数点的数字
char grade = 'A'; // 字符型,只能装单个字符
bool isPassed = true; // 布尔型,只能是true或false
2. 运算符与表达式
运算符就像厨房里的各种刀具,不同的刀具有不同的用途。
int a = 10, b = 3;
int sum = a + b; // 加法,结果为13
int diff = a - b; // 减法,结果为7
int product = a * b; // 乘法,结果为30
int quotient = a / b; // 整数除法,结果为3(注意:不是3.33)
int remainder = a % b; // 取余,结果为1
3. 控制流
控制流就像是你烹饪时的决策过程,根据不同条件采取不同行动。
条件语句
if (score >= 90) {
cout << "优秀!";
} else if (score >= 60) {
cout << "及格";
} else {
cout << "不及格,加油!";
}
循环语句
// for循环,就像是按部就班地完成一系列任务
for (int i = 0; i < 5; i++) {
cout << i << " "; // 输出:0 1 2 3 4
}
// while循环,就像是"只要条件满足,就一直做"
int j = 0;
while (j < 5) {
cout << j << " "; // 输出:0 1 2 3 4
j++;
}
二、类和对象
面向对象编程是C++的精髓所在,这就像从简单的小饭馆升级到了星级酒店的厨房管理。
1. 类的定义与对象创建
类就像是一个蓝图,定义了对象应该具有的属性(数据成员)和行为(成员函数)。
class Car {
private:
string brand;
int speed;
public:
// 构造函数
Car(string b) : brand(b), speed(0) {}
// 成员函数
void accelerate() {
speed += 10;
cout << brand << "加速了,当前速度:" << speed << "km/h" << endl;
}
void brake() {
if (speed >= 10) speed -= 10;
else speed = 0;
cout << brand << "刹车了,当前速度:" << speed << "km/h" << endl;
}
};
// 创建对象
Car myCar("奔驰");
myCar.accelerate(); // 输出:奔驰加速了,当前速度:10km/h
myCar.brake(); // 输出:奔驰刹车了,当前速度:0km/h
2. 继承与多态
继承就像是"青出于蓝而胜于蓝",子类继承父类的特性并可以扩展新功能。
class ElectricCar : public Car {
private:
int batteryLevel;
public:
ElectricCar(string b) : Car(b), batteryLevel(100) {}
void chargeBattery() {
batteryLevel = 100;
cout << "电池已充满!" << endl;
}
// 重写父类方法,这就是多态
void accelerate() override {
Car::accelerate(); // 调用父类方法
batteryLevel -= 5;
cout << "电池剩余:" << batteryLevel << "%" << endl;
}
};
多态就像餐厅里的"今日特色",虽然都是一道菜,但不同厨师有不同做法。
三、模板
模板是C++中的"一次编写,多种类型"的神器,就像是可以根据原料自动调整的食谱。
// 函数模板
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
int maxInt = max(10, 20); // 返回20
double maxDouble = max(3.14, 2.71); // 返回3.14
// 类模板
template <typename T>
class Container {
private:
T data;
public:
Container(T value) : data(value) {}
T getValue() {
return data;
}
};
Container<int> intContainer(42);
Container<string> strContainer("Hello");
模板就像是一种"代码复用"的艺术,让你的代码既简洁又灵活。
四、继承和多态
C++的继承和多态机制就像生物界的进化,子类在父类的基础上不断发展壮大。
继承的类型
- 公有继承(public): 最常用,子类可以访问父类的public和protected成员
- 保护继承(protected): 父类的public成员在子类中变为protected
- 私有继承(private): 父类的public和protected成员在子类中都变为private
多态的实现
多态通过虚函数来实现,就像是同一个指令,不同对象有不同的反应。
class Animal {
public:
virtual void makeSound() {
cout << "动物发出声音" << endl;
}
};
class Dog : public Animal {
public:
void makeSound() override {
cout << "汪汪汪!" << endl;
}
};
class Cat : public Animal {
public:
void makeSound() override {
cout << "喵喵喵~" << endl;
}
};
// 多态的魅力
Animal* pet1 = new Dog();
Animal* pet2 = new Cat();
pet1->makeSound(); // 输出:汪汪汪!
pet2->makeSound(); // 输出:喵喵喵~
五、智能指针
智能指针是C++11引入的内存管理利器,就像有了自动清洁的厨房,再也不用担心"垃圾"没处理了。
// 独占所有权的智能指针
unique_ptr<int> p1(new int(42));
// p1会在离开作用域时自动释放内存
// 不能复制unique_ptr
// unique_ptr<int> p2 = p1; // 编译错误!
// 可以移动所有权
unique_ptr<int> p3 = move(p1); // p1现在为空,p3接管了资源
// 共享所有权的智能指针
shared_ptr<int> sp1(new int(100));
{
shared_ptr<int> sp2 = sp1; // 引用计数增加到2
cout << *sp2 << endl; // 输出:100
} // sp2离开作用域,引用计数减为1
// weak_ptr不会增加引用计数,可以避免循环引用问题
weak_ptr<int> wp = sp1;
智能指针的使用让内存管理变得简单而安全,大大减少了内存泄漏的风险。
六、C++11新特性
C++11像是给语言注入了新的活力,添加了许多现代特性。
1. auto关键字
auto让编译器自动推导变量类型,写代码更加简洁。
auto i = 42; // int
auto d = 3.14; // double
auto s = "hello"; // const char*
auto v = vector<int>{1, 2, 3}; // vector<int>
2. 范围for循环
遍历容器元素变得更加简单直观。
vector<int> nums = {1, 2, 3, 4, 5};
// 传统方式
for (size_t i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
// 范围for循环
for (const auto& num : nums) {
cout << num << " ";
}
3. Lambda表达式
函数式编程的精髓,小巧而强大。
auto sum = [](int a, int b) -> int { return a + b; };
cout << sum(3, 4) << endl; // 输出:7
vector<int> numbers = {1, 3, 5, 2, 4};
sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a > b; // 降序排列
});
// numbers现在是{5, 4, 3, 2, 1}
七、异常处理
异常处理就像是烹饪过程中的"意外情况处理方案",让程序在遇到问题时能够优雅地处理。
try {
int* arr = new int[1000000000]; // 尝试分配大量内存
} catch (const bad_alloc& e) {
cout << "内存分配失败:" << e.what() << endl;
}
// 自定义异常
class DivideByZeroException : public exception {
public:
const char* what() const noexcept override {
return "除数不能为零!";
}
};
double divide(double a, double b) {
if (b == 0) {
throw DivideByZeroException();
}
return a / b;
}
try {
cout << divide(10, 0) << endl;
} catch (const DivideByZeroException& e) {
cout << "错误:" << e.what() << endl;
}
八、四种强制类型转换
C++提供了四种不同用途的类型转换操作符,比C语言的强制类型转换更加安全和明确。
// 1. static_cast:基本数据类型转换和向上转型
double d = 3.14;
int i = static_cast<int>(d); // 浮点数转整数
// 2. dynamic_cast:安全的向下转型,运行时检查
Base* basePtr = new Derived();
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);
if (derivedPtr) {
// 转换成功
}
// 3. const_cast:去除const属性
const int c = 10;
int* p = const_cast<int*>(&c);
// 4. reinterpret_cast:进行低级转换,如指针到整数
int* ptr = new int(42);
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
九、设计模式
设计模式是解决特定问题的经验总结,就像是厨师的"独门秘籍"。
1. 单例模式
确保一个类只有一个实例,并提供全局访问点。
class Singleton {
private:
static Singleton* instance;
Singleton() {} // 私有构造函数
public:
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
};
Singleton* Singleton::instance = nullptr;
2. 工厂模式
将对象的创建与使用分离,增加灵活性。
class Product {
public:
virtual void use() = 0;
virtual ~Product() {}
};
class ConcreteProductA : public Product {
public:
void use() override {
cout << "使用产品A" << endl;
}
};
class ConcreteProductB : public Product {
public:
void use() override {
cout << "使用产品B" << endl;
}
};
class Factory {
public:
static Product* createProduct(char type) {
if (type == 'A') return new ConcreteProductA();
else if (type == 'B') return new ConcreteProductB();
return nullptr;
}
};
十、STL(标准模板库)
STL是C++的一大杀器,就像是厨房里的各种高级厨具,极大提高了编程效率。
1. 容器
STL提供了各种容器,满足不同的数据存储需求。
// 动态数组
vector<int> vec = {1, 2, 3};
vec.push_back(4); // 添加元素
// 双端队列
deque<int> dq = {1, 2, 3};
dq.push_front(0); // 在前端添加元素
// 关联容器
map<string, int> scores;
scores["Alice"] = 95;
scores["Bob"] = 89;
// 查找元素
auto it = scores.find("Alice");
if (it != scores.end()) {
cout << it->first << ": " << it->second << endl;
}
2. 算法
STL算法让复杂操作变得简单高效。
vector<int> nums = {3, 1, 4, 1, 5, 9};
// 排序
sort(nums.begin(), nums.end());
// 查找
auto it = find(nums.begin(), nums.end(), 4);
if (it != nums.end()) {
cout << "找到了:" << *it << endl;
}
// 转换
vector<int> squared;
transform(nums.begin(), nums.end(), back_inserter(squared),
[](int x) { return x * x; });
总结
C++是一门深不可测的语言,学习曲线可能有点陡,但掌握了它就像拥有了一把瑞士军刀,几乎可以解决任何编程问题。希望这篇博客能帮助你梳理C++的关键知识点,在复习的道路上更加轻松愉快!
记住,学习编程最重要的是动手实践。看再多的教程,不如亲自写几行代码来得实在。所以,打开你的IDE,开始编码吧!有什么问题随时找我讨论,一起在C++的海洋里遨游!