More Effective C++ 读书摘要(六、杂项)Item32 - 35

基于Android平台下的健康管理APP/基于android的健康管理系统 随着网络科技的发展,移动智能终端逐渐走进人们的视线,相关应用越来越广泛,并在人们的日常生活中扮演着越来越重要的角色。因此,关键应用程序的开发成为影响移动智能终端普及的重要因素,设计并开发实用、方便的应用程序具有重要的意义和良好的市场前景。Android技术作为当前最流行的操作平台,自然也存在着大量的应用服务需求。 本课题研究的是基于Android技术平台的健康管理APP,开发这款健康管理APP主要是为了帮助用户可以不用约束时间与地点进行所需信息。本文详细讲述了健康管理APP的界面设计及使用,主要包括界面的 阅读详情

Item32. 在将来时态下开发程序:

 

作为软件开发人员,我们也许知道得不够多,但我们知道万物都会变化。我们没必要知道什么将发生变化,这么变化又怎么发生,以什么时候发生,在哪里发生,但我们知道:万物总会变化。

 

好的软件能够适应变化。它提供新的特性,适应到新的平台,满足新的需求,处理新的输入。这种软件的灵活性、健壮性、可靠性不是来自于运气。它是那些遵照了现在的要求并关注了将来可能的开发人员设计和实现出来的。这样的优雅地各应变更的软件是那些在未来时态下开发程序的人写出来的。

 

新的函数将被加入到函数库中,新的重载将发生,于是要注意那些潜在的函数调用的二义性;新的类将会加入继承层次,现在的派生类将会是以后的基类;将会编制新的应用软件,函数将在新的运行环境下被调用,它们应该被写得在新平台上运行正确;程序的维护人员通常不是原来编写它们的人,因此应该被设计得易于被别人理解、维护和扩充。

 

一种好的做法是:用C++语言自己来表达设计上的约束条件,而不是用注释或文档。

 

例如,如果一个类被设计得不能被继承,不要只是在其头文件中加个注释,用C++的方法来阻止继承;Item M26显示了这个技巧。如果一个类需要其实例全部创建在堆中,不要只是对用户说了这么一句,用Item M27的方法来强迫这一点。如果拷贝构造和赋值对一个类是没有意义的,通过申明它们为私有来阻止这些操作(见Item E27)。C++提供了强大的功能、灵活度和表达力。用语言提供的这些特性来强迫程序符合设计。

 

避免按照需要随意更改虚函数的声明(“demand-paged”)。应该判断一个函数的含意,以及它被派生类重定义的话是否有意义。如果是有意义的,申明它为虚,即使没有人立即重定义它。如果不是的话,申明它为非虚,并且不要在以后为了便于某人而更改其声明;确保更改是对整个类的运行环境和类所表示的抽象是有意义的(见Item E36)。

 

处理每个类的赋值和拷贝构造函数,即使“从没人这样做过”。他们现在没有这么做并不意味着他们以后不这么做(见Item E18)。如果这些函数是难以实现的,那么申明它们为私有。这样,不会有人误调编译器提供的默认版本而做错事(这在默认赋值和拷贝构造函数上经常发生,见Item E11)。

 

努力提供这样的类,它们的操作和函数有自然的语法和直观的语义。和内建数据类型的行为保持一致:拿不定主意时,仿照int来做。

 

记住:只要是能被人做的,就有人这么做(WQ:莫菲法则)。他们会抛异常;会用自己给自己赋值;在没有赋初值前就使用对象;给对象赋了值而没有使用;会赋过大的值、过小的值或空值。一般而言,只要能编译通过,就有人会这么做。所以,要使得自己的类易于被正确使用而难以误用。要承认用户可能犯错误,所以要将你的类设计得可以防止、检测或修正这些错误(例子见Item M33和Item E46)。

 

努力于可移植的代码。写可移植的代码并不比不可移植的代码难太多,只有在性能极其重要时采用不可移植的结构才是可取的(见Item M16)。

 

将你的代码设计成:当需要变化时,影响是局部的。尽可能地封装;将实现细节申明为私有(例子见Item E20)。只要可能,使用无名的命名空间和文件内的静态对象或函数(见Item E31)。避免导致虚基类的设计,因为这种类需要每个派生类都直接初始化它--即使是那些间接派生类(见Item M4和Item E43)。避免需要RTTI的设计,它需要if...then...else型的瀑布结构(再次参见Item M31,然后看Item E39上的好方法)。每次,类的继承层次变了,每组if...then...else语句都需要更新,如果你忘掉了一个,你不会从编译器得到任何告警。

 

当然,现在时态的思维是必须的。未来时态的考虑只是简单地增加了一些额外约束:
* 提供完备的类(见Item E18),即使某些部分现在还没有被使用。如果有了新的需求,你不用回过头去改它们。
* 将你的接口设计得便于常见操作并防止常见错误(见Item E46)。使得类容易正确使用而不易用错。例如,阻止拷贝构造和赋值操作,如果它们对这个类没有意义的话(见Item E27)。防止部分赋值(见Item M33)。
* 如果没有限制你不能通用化你的代码,那么通用化它。例如,如果在写树的遍历算法,考虑将它通用得可以处理任何有向不循环图。

 

未来时态的考虑增加了你的代码的可重用性、可维护性、健壮性,已及在环境发生改变时易于修改。它必须与进行时态的约束条件进行取舍。太多的程序员们只关注于现在的需要,然而这么做牺牲的是软件的长期生存能力。要与众不同一点,做一个离经叛道者,在未来时态下开发程序。

 

 Item33. 将非尾端类设计为抽象类:

 

假设你正在编写一个处理动物的软件项目。
这是它们的简化定义:

考虑下面的赋值运算:
Lizard liz1;
Lizard liz2;
Animal *pAnimal1 = &liz1;
Animal *pAnimal2 = &liz2;
...
*pAnimal1 = *pAnimal2;

这里有两个问题:第一,最后一行调用的是Animal类的赋值运算符,虽然相关对象的类型是Lizard。结果,只有liz1的Animal部分被修改。这是部分赋值。在赋值后,liz1的Animal成员有了来自于liz2的值,但其liz1的Lizard成员部分没被改变。

 

第二个问题是真的有程序员把代码写成这样。用指针来给对象赋值并不少见,特别是那些对C有丰富经验而转移到C++的程序员。所以,我们应该将赋值设计得更合理的。如Item M32指出的,我们的类应该容易被正确适用而不容易被用错,而上面这个类层次是容易被用错。

 

一个解决方法是将赋值运算申明为虚函数。如果Animal::operator=是虚函数,那句赋值语句将调用Lizard的赋值操作(应该被调用的版本)。然而,看一下申明它为虚后会发生什么:

基于C++语言新近作出的修改,被覆写的虚函数之间的返回值的类型不要求完全一致,但C++的规则强迫被覆写的虚函数之间声明完全一致相同的参数类型。这意味着Lizard类和Chicken类的赋值操作必须能够接受任意类型的Animal对象。也就是说,这意味着我们必须面对这样的事实:下面的代码是合法的:
Lizard liz;
Chicken chick;
Animal *pAnimal1 = &liz;
Animal *pAnimal2 = &chick;
...
*pAnimal1 = *pAnimal2;                 // assign a chicken to
                                                      // a lizard!

这是一个混合类型赋值:左边是一个Lizard,右边是一个Chicken。混合类型赋值在C++中通常不是问题,因为C++的强类型检验将判定它们为非法。然而,通过将Animal的赋值操作设为虚函数,我们打开了混合类型操作的门。

 

只能在运行期区分它们,因为将*pAnimal2赋给*pAnimal1有时是正确的,有时不是。

 

我们也可以使用dynamic_cast(见Item M2)来实现:在混合类型赋值时指出在operator=内部发生了错误,而类型相同时,我们期望按通常的方式完成赋值。下面是怎么实现Lizard的赋值操作:

这个函数只在rhs确实是Lizard类型时将它赋给*this。如果rhs不是Lizard类型,函数传递出dynamic_cast转换失败时抛的bad_cast类型的异常。(实际上,异常的类型是std::bad_cast,因为标准运行库的组成部分,包括它们抛出的异常,都位于命名空间std中。对于标准运行库的概述,见Item E49和Item M35)。

 

我们也可以在不增加复杂度也不花费dynamic_cast的情况下处理这种情况,只要在Lizard中增加一个通常形式的赋值操作:

实际上,给出了后面那个的operator=,也就简化了前者的实现:

现在这个函数试图将rhs转换为一个Lizard。如果转换成功,通常的赋值操作被调用;否则,一个bad_cast异常被抛出。

但是说实话,在运行期使用dynamic_cast进行类型检测,这令我很紧张。

 

最容易的方法是在Animal中将operator=置为private。于是,Lizard对象可以赋值给Lizard对象,Chicken对象可以赋值给Chicken对象,但部分或混合类型赋值被禁止:

不幸的是,Animal也是具体类,这个方法同时将Animal对象间的赋值判定为非法了:
Animal animal1, animal2;
...
animal1 = animal2;                              // error! attempt to call
                                                            // private Animal::operator=

而且,它也使得不可能正确实现Lizard和Chicken类的赋值操作,因为派生类的赋值操作函数有责任调用其基类的赋值操作函数:

后面这个问题可以通过将Animal::operator=申明为protected来解决,但“既要允许Animal对象间的赋值而同时又要阻止Lizard和Chicken对象通过Animal的指针进行部分赋值”的两难问题仍然存在。程序该怎么办?

 

最容易的事情是排除Animal对象间赋值的需求,其最容易的实现方法是将Animal设计为抽象类。作为抽象类,Animal不能被实例化,所以也就没有了Animal对象间赋值的需求了。当然,这导致了一个新问题,因为我们最初的设计表明Animal对象是必须的。有一个很容易的解决方法:不用将Animal设为抽象类,我们创造一个新类--叫AbstractAnimal--来包含Animal、Lizard、Chikcen的共有属性,并把它设为抽象类。然后将每个实体类从AbstractAnimal继承。修改后的继承体系是这样的:

要使得这一切工作,AbstractAnimal类必须是抽象类--它必须至少有一个纯虚函数。在极少见的情况下,你会发现需要创一个如AbstractAnimal这样的类,没有哪个成员函数可以很自然地声明为纯虚函数。此时,传统方法是将析构函数申明为纯虚函数。为了支持多态,基类总需要虚析构函数(见Item 14),将它声明为纯虚的唯一麻烦就是必须在类的定义之外实现它。


(申明一个函数为虚并不意味着它没有实现,它意味着:
* 当前类是抽象类
* 任何从此类派生的实体类必须将此函数申明为一个“普通”的虚函数(也就是说,不能带“= 0”)
)

 

实现纯虚函数一般不常见,但对纯虚析构函数,它不只是常见,它是必须。

 

面向对象设计的目的是:确认有用的抽象,并强迫它们(并且只有它们)成为一个抽象类。

 

我不知道怎么预知一个继承体系将来会如何使用,但我知道一件事:某个抽象在一个context被用到的可能只是凑巧,但多个context都被乃至的抽象通常是有意义的。

 

记住,只有在设计出的类能被将来的类从它继承而不需要它作任何修改时,你才能从抽象类中获得好处。(如果它需要被修改,你不得不重新编译所有使用继承类的代码,你将得不到任何好处。)

 

当你发现需要从一个具体类派生出另外一个具体类时,这并不是唯一一需要引入抽象类的地方。但是,需要通过公有继承将两个具体类联系起来,通常表示需要一个新的抽象类。

 

 

Item34. 理解如何在同一程序中混合使用C++和C:

 

在同一程序里混合使用C++和C之前,请确保你的C++编译器和C编译器兼容。


确认兼容后,还有四个要考虑的问题:名称改编(name mangling),静态变量初始化,内存动态分配,数据结构兼容性。

 

名称改编

 

即C++编译器给程序的每个函数换一个独一无二的名字。在C中,这个过程是不需要的,因为没有函数重载,但几乎所有C++程序都有函数重名(例如,流库就申明了几个版本的operator<<和operator>>)。重载不兼容于绝大部分链接程序,因为链接程序通常无法分辨同名的函数。名变换是对链接程序的妥协;链接程序通常坚持函数名必须独一无二。

 

如果只在C++范围内,名称改编不会影响你。如果你你有一个函数叫drawline而编译器将它变换为xyzzy,你总使用名字drawLine,不会注意到背后的obj文件引用的是xyzzy的。

 

如果drawLine位于C运行库中,那情况就不同了。你的C++源文件包含的头文件中申明为:
void drawLine(int x1, int y1, int x2, int y2);


代码体中通常也是调用drawLine。每个这样的调用都被编译器转换为调用名变换后的函数,所以写下的是
drawLine(a, b, c, d);          // call to unmangled function name
obj文件中调用的是:
xyzzy(a, b, c, d);             // call to mangled function mame
但如果drawLine是一个C函数,obj文件(或者是动态链接库之类的文件)中包含的编译后的drawLine函数仍然叫drawLine;没有名变换动作。当你试图将obj文件链接为程序时,将得到一个错误,因为链接程序在寻找一个叫xyzzy的函数,而没有这样的函数存在。

 

要解决这个问题,你需要一种方法来告诉C++编译器不要在这个函数上进行名变换。如果你调用一个名字为drawLine的C函数,它实际上就叫drawLine,你的obj文件应该包含这样的一个引用,而不是引用进行了名变换的版本。


要禁止名称改编,使用C++的extern "C"指示:

extern "C"可以对一组函数生效,只要将它们放入一对大括号中:

当用C++编译时,你应该加extern 'C',但用C编译时,不应该这样。
通过只在C++编译器下定义的宏__cplusplus,你可以将头文件组织得这样:

 

静态变量的初始化

 

对C++来说,在main执行前和执行后都可能有大量代码被执行。尤其是静态的类对象和定义在全局的、某个命名空间中的或文件体中的类对象的构造函数通常在main被执行前就被调用。这个过程称为静态初始化(参见Item E47)。这和我们对C++和C程序的通常认识相反,我们一直把main当作程序的入口。同样,通过静态初始化产生的对象也要在静态析构过程中调用其析构函数;这个过程通常发生在main结束运行之后。

 

为了解决main()应该首先被调用,而对象又需要在main()执行前被构造的两难问题,许多编译器在main()的最开始处插入了一个特别的函数,由它来负责静态初始化。同样地,编译器在main()结束处插入了一个函数来析构静态对象。产生的代码通常看起来象这样:

所以如果有可能,就尽量用C++来写main函数。只要将C写的main()改名为realMain(),然后用C++版本的main()调用realMain():

这么做时,最好加上注释来解释原因。

 

如果不能用C++写main(),那就有麻烦了,因为没有其它办法确保静态对象的构造和析构函数被调用了。一般都是由编译器来具体实现。

 

动态内存分配

 

C++部分使用new和delete(参见Item M8),C部分使用malloc(或其变形)和free。只要new分配的内存使用delete释放,malloc分配的内存用free释放,那么就没问题。用free释放new分配的内存或用delete释放malloc分配的内存,其行为没有定义。那么,唯一要记住的就是:将你的new和delete与mallco和free进行严格的隔离。

 

看一下这个粗糙(但很方便)的strdup函数,它并不在C和C++标准(运行库)中,却很常见:
char * strdup(const char *ps);         // return a copy of the
                                                        // string pointed to by ps

要想没有内存泄漏,strdup的调用着必须释放在strdup()中分配的内存。但这内存怎么释放?用delete?用free?如果你调用的strdup来自于C函数库中,那么是后者。如果它是用C++写的,那么恐怕是前者。

 

所以要减少这种可移植性问题,就要尽可能避免调用那些既不在标准运行库中(参见Item E49和Item M35)也不在大多数计算机平台下有固定形式的函数。

 

数据结构的兼容性

 

C了解普通指针,所以想让你的C++和C编译器生产兼容的输出,两种语言间的函数可以安全地交换指向对象的指针和指向非成员的函数或静态成员函数的指针。自然地,struct和内建类型(如int、char等)的变量也可自由通过。

 

如果你在C++版本中增加了非虚函数,其内存结构没有改变,所以,只有非虚函数的结构(或类)的对象兼容于它们在C中的孪生版本(其定义只是去掉了这些成员函数的申明)。增加虚函数将打破这种兼容性,因为其对象将会使用一个不同的内存结构(参见Item M24)。从其它struct(或class)继承而来的struct,通常也改变其内存结构,所以有基类的struct也不能与C函数交互。

 

结论是:如果某个structure的定义既可以在C++中编译,又可以在C 中进行编译,在C++和C之间这样相互传递数据结构是安全的。在C++版本中增加非虚成员函数基本不影响兼容性,但几乎其它的改变都将影响兼容性。

 

总结
如果想在同一程序下混合C++与C编程,记住下面的指导原则:
①* 确保C++和C编译器产生兼容的obj文件。
②* 将在两种语言下都使用的函数申明为extern "C"。
③* 只要可能,用C++写main()。
④* 总用delete释放new分配的内存;总用free释放malloc分配的内存。
⑤* 将在两种语言间传递的东西限制在用C编译的数据结构的范围内;C++版本的struct可以包含非虚成员函数。  

 

Item35. 让自己熟悉C++语言标准:

 

C++发生的主要变化:
* 增加了新的特性:RTTI、命名空间、bool,关键字mutable和explicit,对枚举的重载操作,已及在类的定义中初始化const static成员变量。
* 模板被扩展了:现在允许了成员模板,增加了强迫模板实例化的语法,模板函数允许无类型参数,模板类可以将它们自己作为模板参数。
* 异常处理被细化了:异常规格申明在编译期被进行更严格的检查,unexpected()函数现在可以抛一个bad_exception对象了。
* 内存分配函数被改良了:增加了operator new[]和operator delete[]函数,operator new/new[]在内存分配失败时将抛出一个异常,并有一个返回为0(不抛异常)的版本供选择。(见Effective C++ Item 7)
* 增加了新的类型转换形式:static_cast、dynamic_cast、const_cast,和reinterpret_cast。
* 语言规则进行了重定义:重定义一个虚函数时,其返回值不需要完全的匹配了

 

C++的这些变化在标准运行库的变化面前将黯然失色。
*支持标准C运行库。
* 支持string类型。
*支持本地化。
*支持I/O操作。
*支持数学运算。
*支持通用容器和运算。

 

在介绍STL前,必须先知道标准C++运行库的两个特性。
第一,在运行库中的几乎任何东西都是模板。第二,标准运行库将几乎所有内容都包含在命名空间std中。

 

STL基于三个基本概念:容器(container)、迭代器(iterator)和算法(algorithms)。

另外一点:STL是可扩充的。

基于Simulink的PMSM轮毂电机崎岖路面悬架协同控制仿真 本文完成了基于Simulink的PMSM轮毂电机崎岖路面悬架协同控制仿真,实现了:✅ 构建了四轮独立驱动+主动悬架高保真整车模型✅ 实现了Skyhook主动悬架控制✅ 设计了驱动-悬架状态共享与协同决策机制✅ 验证了5 m/s高速下连续颠簸路面稳定通过能力✅ 为高性能移动机器人提供一体化底盘解决方案。 阅读详情

相关推荐

单细胞转录组数据分析全流程:从原始数据到细胞注释

本文详细介绍了单细胞转录组数据分析的全流程,从原始数据读取、环境搭建、数据质控与标准化,到降维聚类、细胞类型注释,以及高级质控与多样本整合。重点阐述了如何利用Seurat等工具进行数据处理,并通过标志基因比对与自动注释方法完成细胞身份鉴定,为研究者提供了一套清晰、可操作的分析指南。

coffee的博客 553

33 将非尾端类(non-leaf classes)设计为抽象类(abstract classes)

假设你正在进行一个项目,用软件来处理动物。只有两种动物:蜥蜴和鸡,如下是组织形式: Animal class 将负责你所处理的所有动物的共同特征具现化,Lizard和Chicken class则分别将Animal特殊化为蜥蜴和鸡: class Animal { public: Animal&amp; operator = (const Animal&amp; rhs); ... };...

hallå的博客 595

uniapp实现app版本发现新版本后,自动更新

app实现自动更新

oldolder的博客 1284

Effective C++ 读书笔记三

实现 Item26:尽可能延后变量定义式出现的时间 Item27:尽量少做转型动作 Item28:避免返回handles指向对象内部成分 Item29:为“异常安全”而努力是值得的 Item30:透彻了解inline函数的里里外外 Item31:将文件的编译依存关系降到最低 继承与面对对象设计 Item32:确定你的public继承塑模出is-a模型 Item33:避免遮掩继承而来的名称 ...

月寒日暖的博客 316

500道C++面试高频题解析(附答案、实战示例与进阶追问)

本文提供500道C++面试高频题的详细解析,涵盖基础概念到进阶应用,包括面向对象编程、内存管理、现代C++特性、并发编程等核心考点。每道题配有实战示例和进阶追问,帮助开发者突破八股文局限,掌握解决实际问题的能力,适合准备C++技术面试的工程师系统复习。

weixin_29002595的博客 312

STM32驱动AD7779:双极性电源下8通道同步ADC的SPI配置与数据采集实战

本文详细介绍了在双极性电源供电下,使用STM32通过SPI接口驱动AD7779同步ADC芯片实现8通道高精度数据采集的实战经验。重点解析了电源设计、抗干扰处理、寄存器配置、SPI通信技巧及数据校准方法,帮助工程师解决工业测量中的同步采样与噪声控制难题。

e3f4g5的博客 370

More Effective C++ 读书摘要(目录索引)

一、基础议题 Item 1. 区分指针和引用Item 2. 优先考虑C++风格的类型转换Item 3. 决不要把多态用于数组Item 4. 避免不必要的默认构造函数二、运算符Item 5. 小心用户自定义的转换函数Item 6. 区分自增运算符和自减运算符的前缀形式与后缀形式Item 7. 不要重载"&&"、"||"和","Item 8. 理解new和del

thy专栏 1844

农经权二轮延包—地块示意图生成

本文介绍了地块示意图制作软件的使用方法及模板制作要点。软件通过设置六个参数(示意图模板、属性数据、地块DBF、导航图、地块图片及存放位置)自动生成Word文档,并可导出PDF。文章详细说明了5页Word模板的制作过程,包括页脚三栏设置和页码插入技巧,支持每户最多28个地块的情况。同时指出该软件生成的图片分辨率(300dpi)满足清晰度要求,并提及软件免费提供插件但收费提供后续服务。

weixin_47364423的博客 1116

More Effective C++ 读书摘要(auto_ptr的一个实现)

下面是两个auot_ptr的实现。第一个版本文档化了类的接口并在类的定义体外面实现了所有的成员函数。第二个版本将所有的成员函数都实现在定义体内了。 在风格上,第二个实现不如第一个,因为它没有将类的接口从实现中分离出来。但是auto_ptr只是一个简单的类,所以第二个实现比第一个清晰得多。这是把auto_ptr的接口和实现分开的版本:templateclass auto_ptr {

thy专栏 1250

骚戴笔记公告

骚戴笔记公告

我从不打没有准备的仗! 2万+

【YOLOv11工业级实战】27. TensorRT量化实战:FP16/INT8极致加速!边缘设备YOLOv11推理速度提升4倍,精度损失控制在1.5%内

摘要:本文针对智慧园区200路摄像头实时分析的工业痛点——RTX 3080单卡仅能处理12路视频流(YOLOv11-nano FP32精度45FPS,需≥120FPS且精度损失≤3%),提供TensorRT量化完整解决方案。从原理解析(FP16/INT8精度差异与量化逻辑)到实操落地(ONNX转换、FP16引擎构建、INT8精细校准),全程给出可复用代码。实测显示:FP16量化后速度达128FPS(×2.8),精度损失0.2%。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1722

More Effective C++ 读书摘要(五、技巧1)Item25 - 27

 Item25. 使构造函数和非成员函数具有虚函数的行为:有三个类,注意其继承关系:class NLComponent { //用于 newsletter components public: // 的抽象基类 ... //包含只少一个纯虚函数}

thy专栏 1077

STM32CubeIDE开发环境搭建与GPIO控制实战

嵌入式开发中,MCU开发环境构建是软硬件协同的起点,其核心在于工具链选型、外设抽象层级与调试可靠性。HAL库作为ST官方标准硬件抽象层,通过统一接口屏蔽芯片差异,显著提升工程可移植性;而STM32CubeIDE则以图形化配置+自动生成代码的方式,实现‘配置即代码’的确定性开发范式。该组合在教学验证、原型迭代和中小规模量产中具备高性价比技术价值,广泛应用于智能传感、工业HMI及IoT终端等场景。本文聚焦STM32CubeIDE 1.15.0环境部署、MyST账户与固件包管理、ST-LINK驱动校验,以及基于H

weixin_33531560的博客 81

More Effective C++ 读书摘要(五、技巧3)Item30 - 31

Item30. 代理类: 实现二维数组 对于C++内置的数组,如data[][],第一个[]返回的是一个数组,第二个[]从这个返回的数组中再去取一个元素。我们可以通过重载Array2D类的operator[]来玩同样的把戏。Array2D的operator[]返回一个新类Array1D(代表一维数组)的对象,再重载Array1D的operator[]来返回所需要的二维数组中的元

thy专栏 1034

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

More Effective C++ 读书摘要(五、技巧2)Item28 - 29

Item28. 智能(smart)指针:当你使用智能指针替代C++的内建指针(dumb pointer),你就能控制下面这些方面的指针的行为:构造和析构(Construction and destruction)、拷贝和赋值(Copying and assignment)、解引用(Dereferencing)大多数智能指针模板看起来都象这样: template

thy专栏 1012

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

More Effective C++ 读书摘要(三、异常)Item9 - 15

为什么一定要使用异常?答案很简单:异常不能被忽略。Item9.使用析构函数防止资源泄漏:通过智能指针auto_prt将清除代码放入其析构函数里。核心部分如下:templateclass auto_ptr {public: auto_ptr(T *p=0): ptr(p) {} ~auto_ptr() {delete ptr;} private:

thy专栏 915

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

More Effective C++ 整理后感

为什么不是读后感?因为如果仅仅是读完,我还写不出感言,只有在整理、摘要的过程中,才知道哪些是要点,哪些代表了作者的精髓。读完又花了一周多才将这本Scott Meyers的薄薄的大作整理完成,其实整理的过程就是一次再读的过程,我仍然坚持好书读两遍才知其意的观点。像这样的大师级的书恐怕再读个两遍也不为过。这本书不仅仅教会我C++有什么,通过C++能实现什么,更重要的是它教会我:如果C++现在不提供

thy专栏 834

More Effective C++ 读书摘要(一、基础议题 二、运算符)Item1 - 8

〇、“引言”约定与术语:1.指针加p,引用加r。2.(在对operator==)的调用中,lhs和rhs,分别为“left-hand side”、“right-hand side”的缩写。3.ctor表示“constructor”,dtor表示“destructor” 一、基础议题Item 1. 区分指针和引用:以下情况应该使用引用->①当知道要指代某个对象并且不会再指代其他的东西②当实现

thy专栏 820

More Effective C++ 读书摘要(四、效率)Item16 - 24

Item16. 记住80-20准则:80-20准则说的是大约20%的代码使用了80%的程序资源;大约20%的代码耗用了大约80%的运行时间;大约20%的代码使用了80%的内存;大约20%的代码执行80%的磁盘访问;80%的维护投入于大约20%的代码上;通过无数台机器、操作系统和应用程序上的实验这条准则已经被再三地验证过。80-20准则不只是一条好记的惯用语,它更是一条有关系统性能的指导方针,它

thy专栏 810

深挖C++:类和对象(中)

(先进后出)

xys_678的博客 254

C++移动构造函数详解

移动构造函数是C++11引入的一种特殊构造函数,用于从临时对象(右值)"窃取"资源来初始化新对象,而不是进行昂贵的深拷贝。char* data;public:// 移动构造函数:参数是右值引用 &&// 关键:把源对象的资源置空。

拒绝AI文,努力在AI时代写出感动人心的好文章 394

ThunderKittens 深度解析:一个不基于 MLIR 的 C++ 模板 GPU DSL

Triton 是"让更多人能写 GPU kernel",ThunderKittens 是"让会写的人写得更爽"。前者用 MLIR 换易用性,后者用 C++ 模板换可控性。它们不是替代关系,而是覆盖了 GPU 编程光谱的两端。ThunderKittens 的出现,本质上是对"GPU DSL 必须基于 MLIR"这一默认假设的挑战。编译期类型系统本身就可以是一个强大的 DSL 基础设施,不需要中间 IR,不需要黑盒 pass,也能实现 tile 级抽象和零运行时开销。

Maxwell_Newton的博客 349

跟我学c++中级篇—类型定义的方式

本文系统阐述了编程中类型定义的重要性及c++中的实现方式。重点对比了宏定义、typedef与modern using三种机制,指出using在可读性、灵活性和模板支持上的优势,推荐优先使用。同时提醒开发者注意别名滥用、类型歧义、错误信息冗长等问题,强调统一规范与合理设计。最终结论:在现代c++开发中,应以using为主,兼顾简洁性与可维护性,避免陷入命名混乱与编译困境。

fpcc的专栏 88

【C++——类和对象(上)】筑基篇:以封装奠定面向对象之基

本文系统梳理C++类与对象的核心知识点,涵盖类的定义、访问限定符(public/private)、类作用域、对象实例化及内存布局。重点解析封装思想、this指针机制、空类大小为1字节的原因,以及类与对象在内存中的存储差异。通过对比C语言结构体与C++类,揭示面向对象设计的优势:数据保护、接口统一、命名隔离与代码可维护性提升。内容由浅入深,适合作为学习笔记与复习参考。

2602_95684935的博客 497

C++ 函数模版

模板参数:● template ,T 就是类型占位符,名字可以自定义,习惯用T● 占位符可以在函数返回值、形参、函数内部当作类型使用使用要点模板代码一般写在头文件:编译器需要看到完整模板源码,才能在每个编译单元完成实例化全局函数、类内成员函数都可以写成模板实例化发生在编译阶段,不是运行时隐式实例化:调用时编译器自动推导实参类型,生成对应版本函数。

2501_94041724的博客 307

C++ 运行时多态与虚函数机制全面剖析【面试重点】

构成C++ 运行时多态必须是基类的指针或者引用调用虚函数。被调用的函数必须是虚函数,并且派生类必须对该虚函数完成重写/覆盖(Override)。只有基类的指针或引用才能既指向基类对象,又指向派生类对象(切片机制);而只有完成了虚函数重写,派生类与基类才具备不同的函数行为,达到“指向谁就调用谁”的效果。在类成员函数的前面加上virtual关键字修饰,该成员函数就成为了虚函数。public:// 成员函数前加 virtual 修饰,声明为虚函数。

Fuyo_0209的博客 450
上一篇: More Effective C++ 读书摘要(五、技巧3)Item30 - 31
下一篇: More Effective C++ 读书摘要(auto_ptr的一个实现)
thy38
博客等级 码龄19年 184粉丝 116原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值