C++学习笔记----9、发现继承的技巧(四)---- 多态继承(3)
文章浏览阅读1.1k次,点赞32次,收藏8次。这意味着下面的代码将一个double单元格到一个string单元格是可以的,即使只提供了两个operator+的实现:一个是两个double单元格相加,一个是两个string单元格相加。首先,除了提升的设计,还缺失一个属性:从一个单元格类型转换为另一个的能力。与拷贝构造函数外观类似,但是它不是同一个类的对象的引用,而是一个同胞类的对象的引用。从面向对象设计的角度,新的SpreadsheetCell层次结构的实现确定是一次提升。其次,怎么实现单元格的重载的操作符是一个有趣的总是,有几种可能的方法。
C++学习笔记----9、发现继承的技巧(五)---- 多重继承(1)
文章浏览阅读783次,点赞32次,收藏13次。我们前面提到过,多重继承常被认为是面向对象编程中复杂且没有必要的部分。这就仁者见仁,智者见智了,留给大家去评判。本节解释c++中的多重继承。
C++学习笔记----9、发现继承的技巧(五)---- 多重继承(2)
文章浏览阅读689次,点赞18次,收藏4次。DogBird类仍然需要显式指出哪个父类的eat()成员函数被使用,但是Dog与Bird产生的任何不明确都有同样的成员函数,而不是因为它们都继承自同样的类。这种层次结构的类类型在c++中是允许的,但名字不明确仍会产生。例如,如果Animal类有一个公共的成员函数叫做sleep(),该成员函数在DogBird对象上不能被调用,因为编译器不知道到底是去调用Dog还是Bird继承的版本。使用这些“钻石形状”的类层次结构的最好的方式是使最顶部的类是一个所有成员函数声明为干净的virtual的抽象类。
C++学习笔记----9、发现继承的技巧(六)---- 有趣且令人迷惑的继承问题(1)
文章浏览阅读882次,点赞30次,收藏5次。扩展类为许多问题打开了潘多拉魔盒。类的什么特点可以或不可以修改?什么是非公共继承?什么是虚的基类?这些问题,可能更多,会在接下来进行讨论。
C++学习笔记----9、发现继承的技巧(六)---- 有趣且令人迷惑的继承问题(2)
文章浏览阅读998次,点赞19次,收藏20次。Derived类可以定义与在基类中继承的构造函数同样的参数列表的构造函数。然而,因为Derived类用单独的float类型的参数定义它自己的构造函数,使用单独的float类型的参数的基类中继承的构造函数就被隐藏了。例如,如下的Derived类尝试继承Based1与Base2的所有构造函数,对于基于float的构造函数就产生了不确定性。这个技术使用了using声明来显式包含了继承类中的成员函数的基类定义。只用提供的Base构造函数就可以构建一个Base对象,或者是缺省的构造函数,或者是接受int的构造函数。
C++学习笔记----9、发现继承的技巧(六)---- 有趣且令人迷惑的继承问题(3)
文章浏览阅读488次,点赞7次,收藏10次。在c++中,可以使用一个对象调用一个static成员函数,但是因为成员函数是static,它没有this指针,也不能访问对象自身,所以与用类名调用是等价的。注意:static成员函数用它被定义的类的名字圈定,但是它们不是应用于特定对象的成员函数。如果有一个继承类中的static成员函数与基类中的static成员函数一样,实际上拥有的是两个独立的成员函数。它调用了Derived中的继承Base的构造函数。因为static成员函数属于它的类,在两个不同的类上调用同样名字的成员函数实际上调用的是各自的成员函数。
C++学习笔记----9、发现继承的技巧(六)---- 有趣且令人迷惑的继承问题(4)
文章浏览阅读596次,点赞19次,收藏19次。记住,例如,Java与C#只是允许重载公共的与受保护的成员函数,私有的成员函数不行。例如,下面的类是汽车模拟器的一部分,预测了基于它的油箱与所剩的燃料的英里数。getMilesLeft()成员函数执行了基于它自身的两个成员函数:getGallonsLeft()是公共的,和getMilesperGallon()是私有的,的结果的计算。通过重载这个私有的成员函数,新的类完全改变了基类中既有的,没有改变的,公共的成员函数的行为。注意:重载私有的与受保护的成员函数是一个好的方式来改变类的某些属性而不需要大的改造。
C++学习笔记----9、发现继承的技巧(六)---- 有趣且令人迷惑的继承问题(5)
文章浏览阅读793次,点赞8次,收藏6次。如果不想修改实现,只想改变成员函数的访问标识符,优选的方式是简单添加一个using声明在重载类定义中用期望的访问标示符。继承类中重载的成员函数与基类相比可以有不同的缺省参数。在Shy中的talk()的受保护的版本恰当地重载的Gregarious::talk()成员函数。它证明了使成员函数在继承类中受保护确实重载了成员函数(因为重载类版本被正确调用),但是它也证明如果基类使其为公共的,无法整体加强受保护的访问。唯一有用的修改成员函数访问标示符的方式是通过提供限制更小的访问符给到受保护的成员函数。
C++学习笔记----9、发现继承的技巧(六)---- 有趣且令人迷惑的继承问题(6)
文章浏览阅读463次,点赞22次,收藏8次。然而,c++的属性提供了对象的运行时观点。这在本章前面也讨论过了。如果继承类省略了拷贝构造函数或operator=,在继承类中的数据成员会被提供缺省的拷贝构造函数或operator=,基类拷贝构造函数或operator=会被用于基类中指定的数据成员。注意:当需要在继承层次结构中的拷贝功能时,专业c++开发者通用的方法是实现多态clone()成员函数,因为单纯依赖标准拷贝构造函数与拷贝赋值操作符是不够的。前面已经学到,重载成员函数好用的原因是在成员函数与其实现之间是间接层次,而不是对象有内建的自身类的知识。_继承的拷贝构造函数
C++学习笔记----9、发现继承的技巧(六)---- 有趣且令人迷惑的继承问题(7)
文章浏览阅读516次,点赞5次,收藏18次。在这种情况下,当从继承类的构造函数中调用时,编译器使对Dog与Bird构造函数中的对Animal构造函数的调用失效,取而代之的是调用了Animal基类的缺省构造函数,这样就需要Animal的protected缺省构造函数。C++有另外的方法,叫做虚基类,来解决这种问题,如果你确实想让共享父类有自身的功能的话。在不用虚基类的情况下,在DogBird对象上调用sleep()会是不明确的,因为DogBird有两个Animal的子对象,一个来自于Dog,一个来自于Bird,所以会产生编译器错误。
C++学习笔记----9、发现继承的技巧(七)---- 转换(1)
文章浏览阅读974次,点赞38次,收藏20次。我们来看下将一种数据类型转换为另一种数据类型中的一些令人迷惑的地方。C++提供了五种类型转换:const_cast(),static_cast(),reinterpret_cast(),dynamic_cast()与std::bit_cast()。对于static_cast对于继承还有一些内容要讨论。现在你应该能够很熟练地书写自己的类,理解了类继承,是时候来详细探索一下这些转换了。注意旧的C风格的比如(int)myFloat在C++中仍然可以用,并且在既有代码中还大量使用着。
C++学习笔记----9、发现继承的技巧(七)---- 转换(2)
文章浏览阅读1.2k次,点赞28次,收藏16次。下面的表总结了应用于不同情的转换。情形转换去除常量特性显式进行语言支持的转换(例如,int到double,int到bool)显式进行支持用户定义的构造函数或转换的转换将一个类的对象转换为另一个(不相关的)类的对象bit_cast()相同层次结构的类中一个类的对象指针到另一个类的对象指针推荐dynamic_cast()或static_cast()相同层次结构的类中一个类的对象引用到另一个类的对象引用推荐dynamic_cast()或static_cast()类型指针到无关的类型指针。
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(2)
文章浏览阅读797次,点赞19次,收藏16次。模块文件只包含类定义,文件原型,等等,但是不包含任何函数或成员函数的实现,即使这些实现就在接口文件中。这意味着修改在模块接口文件中的一个函数或成员函数实现不会要求重新编译使用那个模块的用户,只要不涉及接口部分,例如,函数头(=函数名,参数列表,与返回类型)。例如,如果模块有一个很大的公共接口,可能不要用实现来妨碍接口就会好一些,这样用户可以有一个提供了什么的整体更好的观感。模块实现文件通过以.cpp结尾。注意:所有模块中与模块实现中的导入声明必须在文件的头部,在命名模块声明之后,但是在其它声明之前。
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(3)
文章浏览阅读1k次,点赞24次,收藏17次。子模块与分区的的区别是子模块结构对于模块的用户是可见的,允许用户单独只导入那些想要用的子模块。如前所述,当在另外一个不是person模块的一部分的源文件中导入person模块,例如在test.cpp文件的盒子中,就没有隐式地继承person模块接口文件中的std导入声明。为了打破这种循环依赖,可以将在datamodel接口文件中需要的datamodel:person分区的功能移到另外一个分区,该分区按顺序被datamodel:person接口分区文件与datamodel接口文件导入。对分区来说不是这样。
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(4)
文章浏览阅读250次,点赞4次,收藏5次。这是正确的--它没有显式导出,但是它是隐式导出的,因为Adder类被导出,Impl类在Adder类中被声明。在该章节中,解决方案要求两个文件:一个主模块接口文件和一个模块实现文件。在模块接口分区文件中不需要声明分区,也可以在模块实现分区文件中进行声明,在一个以.cpp为扩展名的正常源代码文件中,在这种情况下,它是一个实现分区,有时候叫内部分区。原因是Adder::Impl类是私有模块部分的一部分,因此Adder模块的消费者无法访问。在这个私有模块部分定义的任何东东都不会导出,因此对模块的消费者也不可见。
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
文章浏览阅读523次,点赞9次,收藏12次。还有,在前面章节中提到过,导入合适的模块,比如:std或std.compat,不会使任何定义在模块中的C风格的宏对导入的代码可用。在使用C标准库中的C风格的宏时要记住,这特别重要。既然命名的std与std.compat模块不会使assert()宏对于导入代码可用,既然是一个C标准库头文件,因此不保证可导入,必须使用#include 来访问assert()。注意:直到c++23,的使用C标准库头文件是过时的,从c++23开始,它们的使用不再过时,但不鼓励。
C++学习笔记----10、模块、头文件及各种主题(二)---- 预处理指令
文章浏览阅读902次,点赞14次,收藏11次。使用#include预处理指令来包含头文件的内容。还有一些预处理指令。下面列表展示了一些常用的预处理指令:预处理指令功能通用场景[file]文件名的内容插入到指令位置的代码中几乎总是用于包含头文件以便代码可以使用定义在其它地方的功能每个标识符[id]出现的地方都用[value]替换常用于C定义常数或宏。c++对于常数与大部分类型的宏提供了更好的方法。宏可能会危险,所以要小心使用。使前面使用#define定义的[id]失效如果定义的标识符只要求在限定范围的代码中使用。#else。
C++学习笔记----10、模块、头文件及各种主题(三)---- 连接
文章浏览阅读826次,点赞9次,收藏10次。本节讨论C++中连接的概念。C++源文件首先被预处理器处理,它处理所有的预处理指令,结果为翻译单元。所有的翻译单元独立地被编译为对象文件,包含了机器执行码,但是函数的引用还没有定义。解析这些引用是最后阶段,连接器,连接所有的对象文件一起形成最终的可执行文件。技术上讲,在编译过程中还有一些步骤,但对于我们讨论来讲,这个简化的观点已经足够了。在C++翻译单元中的每个名字,包含了函数与全局变量,有连接或无连接,这指出了在哪儿可以定义该名字,从哪儿可以访问到它。
C++学习笔记----10、模块、头文件及各种主题(四)---- 头文件
文章浏览阅读728次,点赞26次,收藏3次。单个翻译单元可以只有一个变量、函数、类类型、枚举类型、概念或者模板的定义。对于有些类型,允许多重声明,但是不允许多重定义。更进一步,在整个程序中只能有一个非内联函数与非内联变量的定义。对于头文件,比较容易破坏单一定义规则,造成重复定义。下一节我们讨论如何通过头文件避免这样的重复定义。在模块之间,破坏单一定义原则是比较难的,因为每一个模块与其它模块进行了更好的隔离。这样做的一个主要原因是在模块中的实体不会从其它模块导出,其他模块拥有模块连接,因此从其它模块的代码无法访问。
TensorFlow面试整理-给定一个任务(如图像分类、文本分类),如何从头构建一个TensorFlow模型?
文章浏览阅读413次。构建一个 TensorFlow 模型来执行图像分类或文本分类任务的步骤基本类似,虽然数据类型不同,但核心流程相同。以下将以 图像分类任务 和 文本分类任务 为例,展示如何从头构建 TensorFlow 模型,覆盖数据预处理、模型构建、编译、训练和评估的完整流程。文本分类任务的第一步是将文本数据转换为适合神经网络处理的数值格式,通常使用 tf.keras.preprocessing.text.Tokenizer 和 tf.keras.preprocessing.sequence.pad_sequences。
今日推荐
周排行