CircuitPython故障排除:从状态LED解读到安全模式修复
2026/5/15 21:07:34
C++ 中面向对象编程(OOP)核心概念——类的定义、封装、继承及类层次结构——的清晰概述。以下是对该内容的系统性梳理与补充说明,便于深入理解:
Name,Age),可为基本类型、指针、其他类对象等。Change(),Retire()),可访问/修改本类数据成员。private:仅限类内部成员函数访问(默认访问级别);public:对类外代码完全开放;protected:类内 + 派生类可访问,但外部不可见(用于继承场景)。~ClassName();自动调用,用于清理资源(如delete[] Name);char *Name),需手动实现深拷贝构造函数、赋值运算符重载、析构函数(即“三法则”或 C++11 后的“五法则”)以避免浅拷贝引发的内存错误。public继承:基类public成员在派生类中仍为public;protected保持protected;private不可访问。protected/private继承较少使用,会进一步限制访问权限。Manager::Level);virtual关键字);Employee::Retire()显式调用被隐藏/重写的基类函数。Manager(char* n, int a, int l) : Employee(n,a), Level(l) {})。| 特性 | 实现机制 | 示例说明 |
|---|---|---|
| 封装 | 访问控制符 + 成员函数接口 | private数据仅通过public函数操作 |
| 继承 | class Derived : access Base | Manager复用并扩展Employee功能 |
| 多态 | virtual函数 + 指针/引用动态绑定 | Employee* p = new Manager; p->Retire();调用Manager::Retire()(若重写且声明为virtual) |
✅最佳实践提醒:
char* Name),务必在析构函数中delete[] Name,并在构造函数中new char[strlen(name)+1];std::string替代char*可自动管理内存,避免常见错误;virtual ~Employee() = default;,防止派生类对象通过基类指针删除时未调用派生类析构函数(内存泄漏风险)。char* Name)的类中,必须显式定义拷贝构造函数和赋值运算符重载,否则编译器会自动生成默认的浅拷贝(shallow copy)版本,这极易引发严重运行时错误。原因和后果如下:编译器生成的默认拷贝构造函数和赋值运算符执行的是按字节复制(bitwise copy):
int Age),复制值是安全的;char* Name),它只复制指针地址,而非指针所指向的动态内存内容→ 多个对象的指针指向同一块堆内存。这就导致:
delete[] Name,对同一内存释放两次 → 未定义行为(程序崩溃、内存损坏);Name修改字符串,另一个对象会“意外”看到相同修改(因共享内存),破坏封装与独立性。🔑 这就是著名的“三法则(Rule of Three)”(C++11 后扩展为“五法则”):
若类需要自定义以下任一函数,通常也需要显式定义其余几个:
- 析构函数(因管理资源)
- 拷贝构造函数(需深拷贝)
- 拷贝赋值运算符(需深拷贝 + 自我赋值检查 + 旧资源清理)
(+ C++11)移动构造函数、移动赋值运算符
Employee为例):classEmployee{char*Name;intAge;public:Employee(constchar*name,intage){Name=newchar[strlen(name)+1];strcpy(Name,name);Age=age;}// ❌ 缺失拷贝构造函数和 operator= → 编译器生成浅拷贝!~Employee(){delete[]Name;}};// 危险使用:Employeee1("Alice",30);Employee e2=e1;// 调用默认拷贝构造函数 → e1.Name 和 e2.Name 指向同一内存!// e1 和 e2 析构时均执行 delete[] Name → double free!✅ 正确做法(深拷贝实现):
// 拷贝构造函数Employee(constEmployee&other):Age(other.Age){Name=newchar[strlen(other.Name)+1];strcpy(Name,other.Name);}// 拷贝赋值运算符(含自我赋值检查 + 旧资源释放)Employee&operator=(constEmployee&other){if(this==&other)return*this;// 自我赋值防护delete[]Name;// 释放当前资源Name=newchar[strlen(other.Name)+1];strcpy(Name,other.Name);Age=other.Age;return*this;}std::string替代char*→ 自动管理内存,拷贝/赋值由标准库保证安全;std::unique_ptr<char[]>)→ 移动语义明确,禁止拷贝,避免误用;