尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

C++ 面向对象编程:类与对象、无名联合体、初始化列表

C++ 面向对象编程:类与对象、无名联合体、初始化列表 总前置C 语言 面向过程 VS C 面向对象 核心对比核心认知1. 编程思想本质区别维度C 语言面向过程 POPC面向对象 OOP核心思路以函数 / 流程为中心拆分步骤关注「怎么做」以类 / 对象为中心拆分实体关注「谁来做、有什么属性」数据与函数关系数据结构体 struct和函数完全分离函数通过参数操作结构体数据无绑定关系类封装属性成员变量 行为成员函数数据和操作绑定为整体访问权限无权限控制结构体成员全局可读写极易误改数据私有 / 保护 / 公有三大访问控制封装保护内部数据代码复用函数复用、结构体复制无继承机制重复代码多继承、多态、复用类大幅减少冗余代码内存管理手动 malloc/free无构造 / 析构变量创建无自动初始化构造函数自动初始化、析构自动释放资源支持 RAII 自动管理内存复合数据类型仅基础结构体不能包含函数不支持联合体封装、常量成员类、结构体、联合体统一支持成员函数、权限、构造、继承2. 最简示例对比学生成绩存储C 语言实现分离式#include stdio.h // 只有数据无操作函数 struct Student { char name[20]; int score; }; // 函数独立在外需要传结构体指针操作数据 void showStu(struct Student* s) { printf(姓名%s分数%d\n, s-name, s-score); } int main() { struct Student s {张三, 90}; showStu(s); return 0; }问题score可以在任意地方随意修改无法校验分数 0~100数据和打印逻辑割裂。C 类实现封装一体#include iostream #include string using namespace std; class Student { private: string name; int score; // 私有数据外部不能直接修改 public: // 构造函数自动初始化 Student(string n, int s):name(n),score(s){ if(score0||score100) score0; // 数据校验 } // 成员函数绑定数据 void showStu() { cout 姓名 name 分数 score endl; } // 提供安全接口修改数据 void setScore(int s){ if(s0s100) scores; } }; int main() { Student s(张三,90); s.showStu(); s.setScore(95); s.showStu(); // s.score 200; 编译报错私有成员禁止外部访问 return 0; }优势数据被保护修改必须走校验接口数据和行为绑定。第一大部分C 类与对象 完整核心知识点基础必学1. 类Class与对象Object基础定义1概念类抽象模板描述一类事物共同的属性成员变量和行为成员函数相当于 C 语言结构体的超级增强版。对象类的实例根据类模板创建出具体实体占用内存一个类可以实例化无数对象。2类完整语法结构class 类名 { // 访问控制符控制外部代码能否访问成员 public: // 公有任意地方可访问 // 成员函数对外接口 private: // 私有仅本类内部成员函数可访问默认权限 // 成员变量核心数据封装隐藏 protected: // 保护本类子类可访问外部不可继承专用 };3C struct VS C class 关键差异核心区分点C 语言struct默认全部公有只能存数据不能写成员函数Cstruct本质和 class 几乎一致默认公有支持成员函数、构造、继承Cclass默认私有工程开发优先用 class 做封装。示例// C struct 默认公有 struct StuStruct { int score; }; // C class 默认私有 class StuClass { int score; }; int main() { StuStruct s1; s1.score 90; // 合法默认public StuClass s2; // s2.score 90; 编译报错默认private return 0; }2. 类的三大核心特性OOP 核心精髓特性 1封装Encapsulation含义将数据和操作数据的方法打包到类隐藏内部私有细节只对外暴露安全接口。目的保护数据防止非法修改简化调用使用者不用关心内部实现实现手段private私有成员 public读写接口get/set 函数对比 C 语言C 无封装结构体数据裸漏无保护机制。标准 get/set 模板class ExamInfo { private: int percent; public: // 获取值 int getPercent() { return percent; } // 安全设置值附带校验 void setPercent(int p) { if(p 0 p 100) percent p; else cout 分数非法 endl; } };特性 2继承Inheritance含义一个类子类 / 派生类复用另一个类父类 / 基类的所有公有、保护成员扩展新功能。对比 C 语言C 语言无继承代码复用只能复制粘贴冗余严重。基础语法class 子类 : 继承方式 父类 {};// 父类 class Person { protected: string name; public: void showName() { cout name endl; } }; // 子类Student继承Person class Student : public Person { private: int id; public: Student(string n,int i){ name n; // 可直接访问父类protected成员 id i; } };特性 3多态Polymorphism含义同一个接口不同对象产生不同行为依托虚函数实现。对比 C 语言C 语言无多态只能用函数指针手动模拟写法复杂。3. 对象的创建、内存、访问方式1两种创建对象方式栈对象自动释放常用ExamInfo e(英语,B);堆对象new 创建手动 delete 释放ExamInfo* p new ExamInfo(高数,true); delete p;C 语言对比C 只能malloc/free无自动构造析构C new 自动调用构造delete 自动调用析构。2成员访问运算符.点运算符栈对象访问e.show();-箭头运算符对象指针访问p-show();C 语言结构体完全一致但 C 没有成员函数。4. 构造函数 析构函数核心基础4.1 构造函数 Constructor规则函数名和类名完全相同无返回值对象创建时自动调用仅执行一次作用初始化对象成员替代 C 语言手动赋值结构体分类无参构造、有参构造、重载构造、拷贝构造对比 C 语言C 无构造函数结构体创建后必须手动赋值容易忘记初始化产生垃圾值。4.2 析构函数 Destructor规则~类名()无参数无返回值一个类只能 1 个析构对象销毁时自动调用作用释放堆内存、关闭文件、释放资源对比 C 语言C 需要手动 free忘记释放造成内存泄漏。示例class Test { private: char* buf; public: // 构造 Test(){ buf new char[100]; // 分配堆内存 } // 析构 ~Test(){ delete[] buf; // 自动释放防止内存泄漏 } };5. 常量对象、常成员函数细节知识点const 类名 对象常量对象只能调用常成员函数不能修改任何成员常成员函数语法void func() const {}函数内禁止修改成员变量对比 C 语言C 无 const 对象区分常量结构体依然可以通过指针篡改。第二大部分构造函数初始化列表 完整详解含 C 对比、使用场景、细节坑点1. 完整语法回顾类名(形参) : 成员1(值), 成员2(值), 联合体成员(值) { 函数体 }2. 初始化列表 VS 函数体内赋值 VS C 语言结构体初始化对比项C 语言结构体初始化C 构造函数初始化列表C 构造函数体内赋值执行时机定义结构体时一次性赋值对象创建瞬间直接初始化成员成员先默认构造再二次覆盖赋值底层性能一次拷贝无额外开销一次构造性能最优两次构造存在多余开销const / 引用支持不支持完美支持直接编译报错自定义类成员无法处理无参构造的类直接初始化无报错编译失败无名联合体C 语言不支持类内联合体直接初始化联合体成员赋值会覆盖内存易乱码3. 四种强制必须使用初始化列表场景核心必记类内const常量成员引用类型成员包含自定义类对象且该类无无参构造函数子类构造调用父类构造函数。示例const 成员只能用初始化列表class Demo { private: const int a; // 常量无法函数内赋值 public: // 正确初始化列表赋值const Demo(int x):a(x){} // 错误写法Demo(int x){ a x; } 编译报错 };4. 高频易错细节梳理初始化顺序和书写顺序无关严格按照类中成员声明从上到下初始化不能用后定义成员初始化前定义成员产生随机垃圾值初始化列表不属于函数体代码执行时机早于{}内部代码。第三大部分类内无名联合体 union 完整详解ExamInfo 案例 C 对比 代码细节 故障总结1. C 语言联合体 VS C 类内无名联合体 核心区别C 语言 union独立数据类型只能基础类型必须定义变量才能访问无法绑定逻辑标记C 类内无名 union嵌入类内部成员直接作为类成员使用配合类的枚举、构造函数自动管理共同特性共用同一块内存大小等于最大成员字节同一时间仅一个数据有效。2. 核心规则复盘无名联合体语法类内直接union { char grade; bool pass; int percent; };访问简化无需联合体对象直接this-grade配套机制必须搭配枚举mode记录当前有效成员否则读取乱码类型限制联合体不能存放string、自定义类带构造析构只能内置基础类型。3. 完整可编译案例代码整合封装、重载构造、初始化列表#include iostream #include string using namespace std; class ExamInfo { private: string courseName; // 课程名 // 枚举标记记录当前联合体哪个成员有效 enum { GRADE, PASS, PERCENTAGE } mode; // 类内无名联合体 union { char grade; // 等级制 A/B/C bool pass; // 通过/不通过 int percent; // 百分制 0-100 }; public: // 构造1等级计分初始化列表同步赋值mode联合体 ExamInfo(string name, char g) : courseName(name), mode(GRADE), grade(g) {} // 构造2通过标识计分 ExamInfo(string name, bool p) : courseName(name), mode(PASS), pass(p) {} // 构造3百分制计分 ExamInfo(string name, int per) : courseName(name), mode(PERCENTAGE), percent(per) {} // 打印成绩函数 void show() { cout courseName : ; switch (mode) { case GRADE: cout grade endl; break; case PASS: cout (pass ? PASS : FAIL) endl; break; case PERCENTAGE: cout percent endl; break; default: cout 数据无效乱码 endl; } } }; int main() { ExamInfo e1(English, B); ExamInfo e2(Calculus, true); ExamInfo e3(CProgramming, 85); e1.show(); e2.show(); e3.show(); return 0; }输出结果plaintextEnglish: B Calculus: PASS CProgramming: 854. 高频故障、易错细节汇总自学避坑核心数据乱码问题只修改联合体成员不更新 mode 枚举 → 读取乱码最高频问题ExamInfo e(Math,90); e.percent 59; // 修改联合体 // 忘记修改modeshow仍然读取百分制没问题若再赋值grade不更新mode直接乱码类型编译限制联合体存储 string 等复杂类 → 编译报错联合体仅支持无构造析构基础类型内存覆盖特性同时给联合体多个成员赋值后赋值直接覆盖前一个数据丢失C 语言原生缺陷C 无法把 union 封装进结构体并绑定标记只能手动维护状态极易出错。5. 内存占用计算示例联合体成员char (1B)、bool (1B)、int (4B) 最大类型 int 占 4 字节 → 联合体总内存 4 字节。 整个 ExamInfo 对象内存string (系统固定大小) 枚举 int (4B) 联合体 (4B)。第四大部分核心知识点总汇总自学复盘、查漏补缺一、基础概念核心要点C 类默认访问权限privateC struct 默认 publicC struct 无访问控制初始化列表执行顺序按成员声明顺序和书写顺序无关联合体内存大小等于内部最大基础类型const、引用成员必须使用初始化列表初始化构造函数无返回值析构函数唯一、无参无名联合体成员直接属于外部类无需对象前缀访问。二、易混淆认知纠正❌ 错误认知初始化列表书写顺序决定成员初始化顺序 → 正确按类内成员声明顺序初始化❌ 错误认知联合体可以同时保存多个有效数据 → 正确内存覆盖仅一个数据有效❌ 错误认知C 语言结构体可以包含成员函数 → 正确C 语言不支持仅 C 支持✅ 正确认知类内无名联合体不需要自定义类型名直接定义使用✅ 正确认知常量对象只能调用 const 修饰的常成员函数三、代码编写高频注意事项构造函数体内禁止给 const、引用成员赋值必须移到初始化列表修改联合体成员时必须同步更新 mode 枚举避免数据乱码类私有成员禁止外部直接访问需封装 public get/set 读写接口子类继承父类时若父类无无参构造必须在子类初始化列表调用父类有参构造联合体中仅可定义基础内置类型禁止定义 string、自定义类等复杂类型。补充C 语言 vs C 面向对象 核心总结C 语言面向过程数据和操作分离无保护、无自动初始化、无复用机制 C 面向对象类封装数据与行为构造 / 析构自动管理资源联合体、继承、多态扩展能力严格权限控制节省内存、代码易维护。
返回列表