05 | 面向对象编程:怎样才能写出一个“好”的类?
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
面向对象编程是一种重要的设计思想,本文从设计思想、实现原则和编码准则三个角度深入探讨了如何写出一个“好”的类。文章强调了面向对象编程的抽象和封装特点,提出了在C++中少用继承和虚函数的建议,以降低对象的成本和避免陷阱。此外,文章介绍了使用特殊标识符“final”来禁止类被继承,简化类的层次关系,并强调了对重要的构造/析构函数使用“= default”来要求编译器使用默认实现。另外,文章还介绍了C++11中的新特性,如委托构造、成员变量初始化和类型别名,以及它们在改善代码质量方面的应用。总的来说,本文提供了丰富的实用经验技巧,帮助读者写出高效、安全、灵活的类。
《罗剑锋的 C++ 实战笔记》,新⼈⾸单¥59
全部留言(72)
- 最新
- 精选
- eletarior关于老师的思考题,我个人的想法是本节的知识点还不足以写一个好的类,文中编码准则和常用技巧里的介绍只是在编码层面给出了建议,但是缺少方法论。少用继承,多用组合,这个建议可以再扩展深入点,比如有的鸟不会飞的例子,其实可以将Fly从Bird类抽离出来,将Fly实现成一个独立的接口类,和Bird类进行组合。 另外既然面向对象的核心是 抽象 和封装,封装可以不言自明,但是抽象是个啥,没有言明,抽象具体到编码里,其实还是需要虚基类和继承语法的。 总而言之,本篇基本是术,而缺少道的深度,所以看罢全文,我还是写不出一个“好”的类。 当然,缺少设计模式思维才是写好一个类最大的障碍,设计模式大部分都是要基于继承关系的,所以老师提到的少用继承,我想并不是说继承不好,而是别使用很多层次的继承,造成不必要的风险和维护难度吧。
作者回复: 1.我的理解,抽象就是“建模”,用类在代码里建立一个现实对象的映射。 2.设计模式更强调对象组合,而不是继承,类模式很少。 3.继承是一种“硬”代码复用,关系比较强,不如组合灵活,我建议少用。当然这还是要建立在对继承等特性有比较深刻认识的基础上。
2020-05-16230 - 甘俊老师您好,这一段有点没看明白,能举个例子体现explicit的作用么? 因为 C++ 有隐式构造和隐式转型的规则,如果你的类里有单参数的构造函数,或者是转型操作符函数,为了防止意外的类型转换,保证安全,就要使用“explicit”将这些函数标记为“显式”。
作者回复: 比如说,有个构造函数A(int x),那么,A a = 1,这里就会有一个隐式构造。大多数时候这个不是问题,但有的时候会导致意外的转换。 使用explicit可以禁止隐式转换,防止意外错误,总是显式的构造,更加安全。
2020-06-07520 - Jason老师讲的很实用,读完很有收获,赞。小贴士里面提到的5,耳目一新,确实很有道理,其他语言如Java、C#、Python的源码文件都是一种类型,只有咱们c++是头文件和实现文件。曾经有Java同事跟我闲聊,你们C++这个头文件啊,鸡肋,我楞了一下,思考了几秒钟,竟然没有反驳的理由。
作者回复: 因为C++继承C,而C这么做是有历史原因的,当时的计算机性能弱内存小,头和实现分离才方便处理。 现在的计算机性能大幅度提升,所以这种方式也就没有太多必要了,我建议尽量用hpp的方式,和其他语言保持一致。
2020-05-16915 - robonix定义一个新的名字空间,把内部类都“提”到外面,降低原来类的耦合度和复杂度。老师,这句话没看懂,能加一个简单的代码示例吗?
作者回复: 大概就是这样 ~~~ namespace xxx { class inner_class {...}; class big_class {...}; } ~~~
2020-05-21313 - Eglinux在 .h 中将类的定义和实现写在一起,这样不是默认所有成员函数都内联了吗?
作者回复: 是的,但是否内联是由编译器决定的,通常只有小的函数才会内联,大的函数不会内联,因为反而成本高不划算。
2020-05-1610 - _smile滴水C课程让我醍醐灌顶,请教下老师关于成员变量初始化的问题,记得以前启蒙老师反复强调不要试图在头文件分配内存给变量赋值,至今为止任不明白为何?难道为了include的时候不会有额外内存开销吗?
作者回复: 头文件会被多个源文件包含,所以在头文件里声明变量就会导致变量被定义了多份,导致编译错误。 但头文件里的类只是定义/声明,并不是实体,所以类的成员变量是没有任务问题的。 回答的可能不是太准确,有不清楚的地方可以再问。
2020-08-0869 - 軟件賺硬幣罗老师,我看标准库和boost库很多继承都超过3层哦。比如iostream里面的,ios_base到ios,再到istream,再到iostream(同时继承ostream),再到fstream。用了三四层继承和虚继承(多重继承)
作者回复: 现实中有很多深层次继承的例子,但不是说这就是好的,实际上iostream就被很多人批评过。
2020-05-1649 - 58using set_type = std::set; 类似这种真的不建议,如果用多了,反而不容易阅读代码。
作者回复: 别名需要控制使用范围,也就是作用域,不能是全局的,而是限制在类或者函数内部,在一个特定的上下文里它才能发挥作用。
2020-11-1828 - 嵇斌1. 面向对象的首要原则 SRP,单一职责原则。这一点特别赞同。另外就是慎用继承,尽量使用组合去实现。分享一个小故事,之前因为代码要写单元测试,使用到了Google Mock,一开始以为 只有虚类才没被Mock,导致很多完全没有必要使用virtual的类使用了virtual,直到有一天看了文档:https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#mocking-non-virtual-methods-mockingnonvirtualmethods 恍然大悟。 2. 类的设计最好遵循RAII,即在构造时完成资源的初始化。但是我觉可能Chrono可能会在后续内存管理的课程中讲这个。
作者回复: 现在C++有很多工具,比如智能指针,可以在外部帮着管理资源,还有对象池模式,集中申请释放。 所以RAII还是要看情况,当然,如果资源确实是与类强相关,那么就用RAII自己管理。
2020-05-167 - Eason Tai有个小问题,为什么要在一些类里面多次书写 public 和 private 关键字呢?是增加可读性或者强调什么嘛?
作者回复: 是的,这大概是借鉴了一点java吧,用public、private来分组不同的逻辑段落,增强可读性。
2020-05-244