计算机
c base
c++ 基础 作用域及生命周期
c++ template
c++ 内存视角
c++ 函数
c++ 基础 基础语法
c++ 性能
c++ 类 基础
c++ 类 对象模型 类析构
c++ 类 设计模式
C++ STL
cmake
CMAKE环境搭建 windows
创建第一个cmakelists.txt
构建稍复杂的项目
动态链接库
EX1
EX1 START
EX1 ANSWER
EX2
EX2 START
EX2 ANSWER
EX3
EX3 START
EX3 ANSWER
变量
控制流程
函数和宏
查找和使用外部库
生成器表达式
qt
qt c++
qt index
qt qml quick
qt ui
qt 多线程
理解QObject 1
理解QObject 4
C++ 技巧 反射
理解QObject 2
理解QObject 3
理解QObject 6
理解 QObject 5
QCoreApplication
QApplication
数据结构
PC问题监控及排查
PC程序性能优化
OS
TOOL
编程漫谈
sealos+frp,搭建内网穿透
host主机配置
C++实战 主题
多线程
生产者-消费者流水线
IO
网络
Bilinotes搭建
编译原理
WEB开发
TS
HTML CSS JAVASCRIPT
本站点使用 MrDoc 构建
-
+
c++ 基础 基础语法
# c++特性 ## RAII ## RTTI RTTI 是 Run-Time Type Information(运行时类型信息)的缩写。 它的核心作用是:在程序运行时,让程序能够识别一个对象或变量的实际数据类型,尤其是在继承和多态的场景下。 简单说:当你有一个基类的指针或引用,指向派生类的对象时,RTTI 允许你查询这个指针/引用真正指向的是哪个类型的对象。 ## std::any、std::function、std::shared_ptr、override ### std::function 存储任何可调用对象,只要签名匹配。可以直接像函数一样调用。 案例1:回调函数 ``` class Button { public: std::function<void()> onClick; // 存储回调函数 void click() { if (onClick) { // 1. 检查是否有注册 onClick(); // 2. 调用回调函数 } } }; int main() { Button btn; // 注册回调 btn.onClick = []() { cout << "Button clicked!\n"; }; // 模拟用户点击 btn.click(); // ← 这里触发回调 return 0; } ``` 案例2:策略模式 # 代码组织 宏、匿名命名空间、类型别名 匿名命名空间:让符号只在当前编译单元(.cpp 文件)可见,类似于 static 的增强版。 ``` // 匿名命名空间:没有名字的 namespace namespace { int internal_counter = 0; // 内部变量 void helperFunction() {} // 内部函数 class InternalClass {}; // 内部类 } ``` 类型别名: // 定义类型别名 ``` using CreatorFunc = std::function<std::shared_ptr<Observable>()>; ``` # 类型安全 dynamic_cast、std::any_cast #### std::any_cast 案例1:配置文件解析器(最常用场景) #### dynamic_cast : 多态继承体系中的向下转型(基类 → 派生类) 使用条件: 基类必须有虚函数(至少一个) 用于指针或引用 ``` dynamic_cast<Derived*>(basePtr); // 指针版本 dynamic_cast<Derived&>(baseRef); // 引用版本 ``` 行为: 指针:转型失败返回 nullptr 引用:转型失败抛出 std::bad_cast 异常 ``` class Animal { public: virtual ~Animal() = default; // 必须有虚函数 virtual void speak() { cout << "Animal\n"; } }; class Dog : public Animal { public: void bark() { cout << "Woof!\n"; } void speak() override { cout << "Dog\n"; } }; class Cat : public Animal { public: void meow() { cout << "Meow!\n"; } }; int main() { Animal* a1 = new Dog(); Animal* a2 = new Cat(); // 向下转型:检查实际类型 Dog* d = dynamic_cast<Dog*>(a1); if (d) d->bark(); // 输出:Woof! Dog* d2 = dynamic_cast<Dog*>(a2); if (!d2) cout << "Not a Dog\n"; // 输出:Not a Dog // 引用版本(危险示例) try { Cat& c = dynamic_cast<Cat&>(*a1); // a1 是 Dog,转型失败 c.meow(); } catch (const bad_cast& e) { cout << "Bad cast: " << e.what() << endl; } delete a1, a2; } ``` 使用向下转型解决的实际问题 问题1:BOSS 战中的特殊交互 ``` // BOSS 会根据玩家职业使用不同技能 class Boss { public: void specialAttack(vector<Character*>& players) { for (auto player : players) { // 问题:BOSS 需要针对不同职业使用不同策略 // 但 players 存的是 Character*,无法直接调用职业特有方法 // 解决方案:向下转型识别职业 if (Warrior* warrior = dynamic_cast<Warrior*>(player)) { // 战士:BOSS 使用缴械,减少怒气 cout << "BOSS 对战士 " << warrior->getName() << " 使用缴械!怒气清零!\n"; warrior->addRage(-1000); // 调用战士特有方法 } else if (Mage* mage = dynamic_cast<Mage*>(player)) { // 法师:BOSS 使用法力燃烧,消耗护盾 cout << "BOSS 对法师 " << mage->getName() << " 使用法力燃烧!护盾清零!\n"; mage->addManaShield(-1000); } else if (Priest* priest = dynamic_cast<Priest*>(player)) { // 牧师:BOSS 使用沉默,无法治疗 cout << "BOSS 对牧师 " << priest->getName() << " 使用沉默!信仰清零!\n"; priest->addFaith(-1000); } } } }; ``` # 控制语句 ```c++ switch(): case 1: case 2: case 3: ``` ## 内存相关 explicit, 声明不做隐式转换 隐式转换可能导致的问题: - 对象构造太多,占内存 - 意外的函数匹配 ```c++ void func(Seconds s) { cout << "Seconds version\n"; } void func(int x) { cout << "int version\n"; } func(10); // 哪个被调用? // 编译器会优先选择精确匹配的 func(int),不会触发转换 // 但如果删除了 int 版本,代码会默默调用 Seconds 版本 ``` ```c++ #include <iostream> using namespace std; class Seconds { public: Seconds(int s) : value(s) {} // 没有 explicit int value; }; void printTime(Seconds s) { cout << "time = " << s.value << " seconds\n"; } int main() { Seconds a = 10; // int -> Seconds,发生隐式转换 printTime(5); // 传 int,自动转换成 Seconds } ``` ## 字符串相关 ```c++ #include <cstring> // 定义和初始化 char str1\[\] \= "Hello"; // 自动计算长度(末尾有\\0) char str2\[10\] \= "Hello"; // 指定长度 char\* str3 \= "Hello"; // 字符串字面量(只读,危险) // 常用操作 strlen(str); // 获取长度(不包括\\0) strcpy(dest, src); // 拷贝(不安全,不检查边界) strncpy(dest, src, n); // 受限制拷贝 strcat(dest, src); // 拼接 ``` ## 左值引用 ```c++ int& ref = x; ``` 右值引用 ```c++ int&& rref \= 10; // 绑定到临时对象 string&& s \= "temp"; ```
peipeo
2026年5月20日 13:04
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码