新闻详情

新闻详情

首页 / 资讯中心 / 详情

类和对象(四)

发布时间:2026/9/30 7:21:59来源:尧图网络
类和对象(四)
在 C 的面向对象编程中构造函数是每个类都绕不开的核心话题。它负责在对象创建时完成初始化是对象生命周期中第一个被调用的成员函数。本文将继续深入探讨构造函数的进阶用法——初始化列表并进一步讲解类型转换与static 成员这两个与对象创建、访问密切相关的知识点。通过本文的学习你将理解为什么某些成员变量必须放在初始化列表中初始化以及如何利用构造函数实现类型之间的转换、如何借助 static 成员实现跨对象的共享数据。构造函数续之前我们所讲的构造函数是用于在实例化对象时对这个对象进行初始化。我们可以显式地定义构造函数不定义时编译器也会自动生成。这里我们再深入讲解构造函数中最重要的部分初始化列表。关于我们之前Date类构造函数的写法是这样的classDate{public:Date(intyear1,intmonth1,intday1){_yearyear;_monthmonth;_dayday;}private:int_year;int_month;int_day;};如果我们写成初始化列表那么这个构造函数应该是这样的Date(intyear1,intmonth1,intday1)//初始化列表的格式:_year(year)//将year的值赋给_year,_month(month)//同理,_day(day){;}初始化列表的写法是一个冒号后跟成员变量括号内部是表达式或变量用于初始化前面的成员变量后面的成员变量初始化都跟在逗号后面。而且在初始化列表中每个成员只能出现一次。函数体内部可以什么都不写我们一般建议将初始化都写到初始化列表当中因为所有的成员变量都要进入初始化列表。成员变量进入初始化列表的顺序与成员变量声明的顺序完全一致这里先进入初始化列表的是_year然后是_month最后是_day。C11 规定我们可以给成员变量设定一个缺省值比如这里我们给_year设定默认值为 2026然后不在初始化列表里面初始化_year。classDate{public:Date(intyear1,intmonth1,intday1):_month(month),_day(day){;}private:int_year2026;//设定缺省值而非赋值int_month;int_day;};对于这样一个构造函数是如何进入初始化列表的呢这里_year先进入初始化列表但是初始化列表没有显式写_year的初始化所以编译器会去找_year的缺省值将它的缺省值赋给_year。后面的成员变量在初始化列表中都显式地写了会用我们设定的值正常初始化。像这样的成员变量我们可以把它的初始化写在初始化列表也可以写在函数体内但有三种变量我们必须写在初始化列表中。引用、const 修饰的变量、没有默认构造函数的类我们都必须在初始化列表中进行初始化。这三类变量存在一个共同点那就是必须在创建时就进行初始化且只能初始化这一次。classTime{public:Time(inthours,intminutes):_hours(hours),_minutes(minutes){;}private:int_hours;int_minutes;};classDate{public:Date(intyear1,intmonth1,intday1):_month(month),_day(day)//必须写在初始化列表中,_i(day),_a(1),_t(4,5){;}private:int_year2026;//设定缺省值而非赋值int_month;int_day;int_i;constint_a;Time _t;};这三类对象必须进入初始化列表的原因都很好理解。关于成员变量进入初始化列表初始化的逻辑我们可以用以下这张图来概括这也就是初始化列表的所有内容了那么在构造函数的函数体内我们可以干什么呢我们可以完成初始化列表做不到的事。比如我们用 malloc 函数申请一块空间的时候都要判断一下是否申请成功这个判断我们就可以放到函数体内完成因为初始化列表做不到。classStack{public:Stack(intn4):_a((int*)malloc(n*sizeof(int))),_top(0),_capacity(n){//判断是否申请成功if(_aNULL){perror(malloc);exit(-1);}}private:int*_a;int_top;int_capacity;};类型转换我们来看一个类classA{public:A(inta1):_a1(a){;}voidPrint(){cout_a1endl;}private:int_a1;};然后我们用2去构造一个类对象能成功吗intmain(){A a12;a1.Print();return0;}结果发现成功了为什么呢这是因为发生了类型转换。在 C 语言中我们知道它支持内置类型转换比如整型和浮点型、指针和整型等等但不支持自定义类型的转换。在 C 中是支持的我们可以把内置类型转换为自定义类型同时也支持自定义类型和自定义类型之间进行转换但需要通过构造函数来实现。内置类型转换为自定义类型这里A a1 2就发生了类型转换2先传过去构造了一个临时对象该临时对象再拷贝构造a1对于这种连续的构造拷贝构造会被编译器优化为直接构造。我们知道临时对象具有常性在之前的 const 引用中我们也知道发生了类型转换的表达式必须使用 const 引用所以我们想给它取别名应该这样写constAa22;不使用 const 修饰就会出现权限放大的问题编译也不通过。这是传一个参数的构造函数那么对于要传两个参数以及更多参数的构造函数呢我们应该如何用内置类型去直接构造classA{public:A(inta11,inta21):_a1(a1),_a2(a2){;}voidPrint(){cout_a1 _a2endl;}private:int_a1;int_a2;};如果我们直接用括号括起来写成A a (1,2)就相当于逗号表达式了实际传过去的参数就变成了一个所以要用大括号括起来A a1{1,2};a1.Print();也可以写成这样Aa1({1,2});自定义类型之间的转换对于自定义类型之间的转换则需要通过相应的构造函数来实现。classA{friendclassB;public:A(inta11,inta21):_a1(a1),_a2(a2){;}voidPrint(){cout_a1 _a2endl;}private:int_a1;int_a2;};classB{public:B(Aa):_b1(a._a1),_b2(a._a2){;}private:int_b1;int_b2;};intmain(){Aa1({1,2});B b1a1;//类A去构造Breturn0;}static成员我们知道每个类对象中都有自己的成员变量它们都是相互独立的那么存在 static 成员会是什么情况这里我们想统计类 C 对象的创建次数但又不想外部可以直接修改那么定义成全局变量显然不合理考虑到类的封装性我们把它定义成 static 成员变量。//统计类C的创建次数classC{public:C(){_ret;}C(constCc){_ret;}private://定义成静态成员变量staticint_ret;};因为_ret属于整个类是所有对象共有的所以它不会进入初始化列表我们需要在类外面初始化它且只能初始化一次需要指定类域来查找。intC::_ret0;//初始化成0然后我们给外部提供一个接口使外部可访问_ret的值从而拿到类对象的创建次数。staticintGet_ret(){return_ret;}因为要访问的成员被static修饰了所以我们也用 static 成员函数来访问该成员它与普通成员函数的区别在于内部不含有 this 指针并且只能访问 static 成员普通成员函数静态和非静态成员变量都可访问。intmain(){C c1;Cc2(c1);C c3;coutc3.Get_ret()endl;return0;}
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

从零搭建AI工程能力:告别调包侠的实战指南 2026/9/30 8:12:28

从零搭建AI工程能力:告别调包侠的实战指南

1. 从零搭建AI工程能力:为什么我劝你别再当“调包侠”“ai-engineering-from-scratch”这个标题,第一次看到的时候我就觉得挺有意思。它不像那些“三天速成大模型”或者“手把手教你微调GPT”之类的标题那么浮夸,反而透着一股子踏实劲儿——从…

阅读更多 →
Flutter跨平台鸿蒙开发实战:宿舍报修系统完整复盘与踩坑指南 2026/9/30 8:12:27

Flutter跨平台鸿蒙开发实战:宿舍报修系统完整复盘与踩坑指南

宿舍报修这个事,估计每个住过集体宿舍的人都经历过:水龙头坏了找不到人修、报修单填完石沉大海、维修师傅上门时间全靠缘分。我接手这个项目时,需求方就三个字——“管起来”。Flutter框架跨平台鸿蒙开发的组合,正好把“一套代码、…

阅读更多 →
小游戏排行榜设计指南:撬动社交裂变与留存的核心引擎 2026/9/30 8:12:21

小游戏排行榜设计指南:撬动社交裂变与留存的核心引擎

小游戏这行,很多人死就死在太把游戏当游戏。你画得再精致,玩法再上头,如果没人看见,一切都等于零。而真正能让一款小游戏从冷启动直接滚成小爆款的,往往不是玩法本身,而是排行榜这类社交功能。说白了&#…

阅读更多 →
MySQL部门薪资Top3:7种写法与RANK、DENSE_RANK全解析 2026/9/30 8:12:21

MySQL部门薪资Top3:7种写法与RANK、DENSE_RANK全解析

"用MySQL求每个部门薪资前三的员工"——这道题在我面试数据岗、后端岗,甚至带新人时都反复出现,但能一口气把逻辑讲透、把不同写法的坑摸清的人其实不多。最常见的翻车现场是:知道窗口函数就写 DENSE_RANK,被追问 RANK …

阅读更多 →
MySQL 8.4批量修改表字符集与排序规则实战方案 2026/9/30 8:12:20

MySQL 8.4批量修改表字符集与排序规则实战方案

最近在给一套跑了快六年的存量库做规范化升级,目标是把所有业务表的字符集从原来的latin1和utf8mb3统一收敛到utf8mb4,排序规则也一并理顺。这活儿看着不大,真动手才发现是个需要细心的批量工程——MySQL 8.4里CHARACTER SET和COLLATION这两个…

阅读更多 →
基于DeepSeek的政务热线民生诉求分类模型部署实践 2026/9/30 8:12:20

基于DeepSeek的政务热线民生诉求分类模型部署实践

简介:这份PDF文档面向政务信息化从业者、数据分析人员及希望将大模型落地于公共服务的开发者,聚焦民生诉求数据的智能分类难题。文档以DeepSeek模型为核心,系统讲解从数据采集、清洗、标注到模型训练、优化、部署及系统集成的完整链路&#x…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉