面向对象高级编程上

面向对象高级编程

  • 一、面向对象高级编程上
    • (1)C++代码基本形式
    • (2)Header中的防卫式声明
    • (3)不带指针类的实现过程
      • 1. 防卫式声明
      • 2. 访问级别
      • 3.构造函数
      • 4.重载
        • 4.1 成员函数(有this)
        • 4.2 非成员函数(无this)
        • 4.3 重载输入输出流
      • 5.常量成员函数
      • 6.参数传递和返回值传递
        • 6.1 参数传递
        • 6.2 返回值
      • 7.友元
      • 8. inline函数
    • (4) 带指针类的实现过程
      • 1. 防卫式声明
      • 2. Big Three
        • 2.1 构造函数
        • 2.2 拷贝构造
        • 2.2 拷贝赋值
        • 2.3 析构函数
      • 3.输出函数
    • (5) 堆、栈与内存管理
      • 1. 栈的生命期
      • 2. 堆的生命期
    • (6) new和delete
      • 1.new
      • 2.delete
    • (7) static
      • 单例
    • (8) 模板
      • 1.类模板
      • 2.函数模板
    • (9) namespace
    • (10) 类与类之间的关系(面向对象的思想)
      • 1.继承
          • 从内存角度看
      • 2.复合
          • 从内存的角度看
          • composition关系下的构造和析构
      • 3.委托
    • (11) 虚函数与多态
        • Template Method
        • 继承+复合关系
        • 继承+委托关系
          • observer

一、面向对象高级编程上

(1)C++代码基本形式

在这里插入图片描述

(2)Header中的防卫式声明

C++头文件中的防卫式声明(也称为包含卫士或头文件保护)是为了防止头文件内容在同一编译单元中被多次包含。这种做法通常使用预处理器指令实现,如下所示:
在这里插入图片描述
防卫式声明的主要目的和优点包括:

避免重复包含:在一个项目中,多个源文件可能都会包含相同的头文件。如果头文件被多次包含,它的内容(如变量定义、函数声明等)将在同一编译单元中出现多次,从而导致编译错误。防卫式声明确保了即使头文件被多次包含,其内容也只被处理一次。

防止编译错误:没有防卫式声明的头文件如果包含多次,可能会引起重复定义的错误。例如,重复的函数定义、类定义或全局变量定义都会导致编译错误。

提高编译效率:通过防止头文件内容的重复包含,可以减少编译器的工作量,提高编译效率。

模块化设计:防卫式声明支持模块化设计,允许开发者在多个文件中重用相同的头文件,而不必担心重复包含的问题。

(3)不带指针类的实现过程

1. 防卫式声明

2. 访问级别

思考哪些类型的数据,放在private下,哪些数据放在public下。
思考需要哪些函数,哪些放在public下,哪些放在private下。

3.构造函数

  • 不需要有返回值,是否需要默认值,参数如何传递(加不加引用),初始列(只有构造函数有),是否需要在函数体内做其他一些事情。
    在这里插入图片描述
  • 构造函数的访问级别是否设为私有
    在这里插入图片描述
    静态局部变量 a。由于其是静态的,它只会被初始化一次,即在第一次调用 getInstance() 方法时。
    静态局部变量 a 的生命周期是从它被创建开始直到程序结束。
    每次调用 getInstance() 方法时,都会返回对同一个静态局部变量 a 的引用。任何后续对 getInstance() 的调用都返回对同一个实例的引用,而不会创建新的对象。

4.重载

  • 注意是否有默认值
    在这里插入图片描述
4.1 成员函数(有this)

在class中的每一个成员函数都默认有一个不可见的参数this,this指向了当前成员函数的调用者。
在这里插入图片描述

在这里插入图片描述

4.2 非成员函数(无this)

在这里插入图片描述

我们想实现复数的三种加法运算符重载。这三种函数绝不可以return by reference,因为他们返回的必然是local对象,在函数体执行完后释放。
语法:typename();

4.3 重载输入输出流

两种选择,一种是成员函数,一种是非成员函数。

当你重载一个操作符作为成员函数时,第一个参数总是调用它的对象实例本身,这对于大多数操作符是适用的,因为它们通常是以对象为中心的操作,比如 obj + something 或 obj == another_obj。

但是,对于流操作符 << 而言,通常的用法是将对象写入输出流,如 std::cout << obj。在这种情况下,输出流对象(如 std::cout)应当是操作符的第一个参数,而要输出的对象实例应当是第二个参数。因为 std::cout 是 std::ostream 类的实例,而不是你自定义类型的实例,所以不能将 << 作为你自定义类型的成员函数来重载,因为这会要求 std::ostream 对象作为成员函数的调用者。

image-20240305161044160

写成 成员函数,用法不符合逻辑,因此只能写为非成员函数。

image-20240305161054047

5.常量成员函数

class里面的函数分为 会改变数据 和 不会改变数据 两种。数据就是this指针所指向的成员变量。

不会改变数据内容的,加上const,用于声明某个成员函数不会修改对象的状态,即这是个只读函数
在这里插入图片描述

6.参数传递和返回值传递

三种:值传递、引用传递、const修饰的引用传递。

6.1 参数传递

在这里插入图片描述

6.2 返回值

在这里插入图片描述
那么什么时候return by value?
如果在函数内部创建了一个变量,并且需要返回该变量,那么考虑值传递,因为当该变量在栈区,函数执行结束后就释放了。

7.友元

在这里插入图片描述
在这里插入图片描述

8. inline函数

函数若在class body内定义完成,便成为inline候选。
是否可以inline由编译器决定,无论加不加inline关键字。
在这里插入图片描述

(4) 带指针类的实现过程

1. 防卫式声明

image-20240305161109504

2. Big Three

字符串里的字符有大有小,所以不能用字符数组来存储,因此在需要的时候开辟内存空间,将指针指向字符串即可(动态分配方式)。
在这里插入图片描述

如果想要实现这样的功能,那么构造函数怎么设计?

image-20240305161120028

image-20240305161124562

2.1 构造函数

image-20240305161130193

2.2 拷贝构造

如果不重写拷贝构造或者拷贝赋值,那么编译器默认的拷贝构造和拷贝赋值函数,是简单的将一个对象的值赋值给另一个对象,也就是说,在有指针成员的情况下,两个对象最后指针指向同一块内存空间,这就是浅拷贝问题。我们想要的是,指向两个不同的独立的内存空间,虽然内存空间里存放的值一样。

image-20240305161134114

浅拷贝会带来堆区的内存重复释放,多次调用析构函数会造成程序崩溃。也会造成内存泄漏,b所指向的空间丢失了。

避免这种情况,也就是深拷贝,如下:

image-20240305161138869

这两种都是调用了拷贝构造函数。

image-20240305161142564

2.2 拷贝赋值

**注意检测自我赋值。**为了正确性与效率。

image-20240305161147241

image-20240305161152442

2.3 析构函数

image-20240305161156213

3.输出函数

在重载<<之前,因为我们实现的是全局函数,又不想声明成MyString类的友元,因此我们需要写一个取得字符指针的函数。

image-20240305161200284

因为ostream可以直接接收字符指针,因此我们取得字符指针传递给ostream即可。

image-20240305161204157

(5) 堆、栈与内存管理

何谓堆、栈?

image-20240305161208780

1. 栈的生命期

在这里插入图片描述
栈是存在某作用域的一块内存空间中。例如当调用函数,函数本身会形成一个stack来存放它接收的参数,以及返回地址。在函数体内声明的任何变量,其所使用的内存块都取自于stack。
c1就是所谓的stack object,其生命在作用域结束后结束,又称为auto object,会自动被清理(调用析构函数)。
在这里插入图片描述
c2是静态对象,作用域结束后生命也不会结束,直到程序结束后,结束生命。
在这里插入图片描述
c3是全局对象,其生命在整个程序结束后结束。

2. 堆的生命期

image-20240305161217914

在这里插入图片描述
new:先分配memory,再调用构造函数。
delete:先调用析构函数,再释放内存。

array new一定要搭配array delete。
在这里插入图片描述

(6) new和delete

1.new

image-20240305161225344

image-20240305161229208

2.delete

析构函数先将字符串指针m_data指向的动态分配的空间销毁,之后再释放指向MyString对象的指针。

image-20240305161234823

image-20240305161239266

注意:array new 一定要搭配 array delete。

image-20240305161243653

(7) static

image-20240305161248127

在没有使用static声明对象的时候,我们创建了三个复数对象c1、c2、c3,这三个对象调用了同一个函数real,但是编译器怎么知道是哪个对象调用的函数real,这个时候凭借的就是this指针。所有成员函数都隐含一个this指针。谁调用real,谁就是this,所以要传入地址。
比如c1调用real,那么传入c1的地址,real里的this指针就是c1。因此不同的对象调用real,传入的this是各自的对象,不同的。

在调用real函数时候,对象的this指针自动传递进去,因此编译器知道是哪个对象调用该函数。

然而,加了static后的数据,与对象脱离,不属于对象,单独在内存中开辟空间。

多个对象拥有同一个静态数据,不属于任何一个对象所独有。比如说:银行系统中的利率,银行的账户对象有多个,但是每个账户共享同一个利率。

静态函数没有this指针,因此不能够像一般函数一样去访问对象中的普通数据,所以只能访问静态数据。

如何调用静态函数?

image-20240305161252570

静态数据成员的定义必须在类外部进行,而且需要在定义时加上数据类型。

单例

诉求:只产生一个对象。

image-20240305161256562

外界无法创建A的对象,因此要提供一个接口可以使外界能取到唯一的A的对象。

但是如果外界一直不使用a,那么这样有点浪费。

image-20240305161300308

这样写的好处是,如果没有人用这个单例,那么该对象就不存在。如果有人使用这个单例,那么该对象有且仅有一份。

(8) 模板

1.类模板

语法:

image-20240305161303920

在类声明中,欲采用通用数据类型的数据成员、成员函数的参数或返回类型前面需要加上类型参数。

image-20240305161306969

2.函数模板

语法:

image-20240305161310632

image-20240305161313825

(9) namespace

东西包装在命名空间中。可以保证同名的东西不会交叉,在各自的命名空间中封装。

(10) 类与类之间的关系(面向对象的思想)

1.继承

inheritance,表示is-a

image-20240305133426721

继承的特性:

  • 父类的数据是可以完整继承下来的。
从内存角度看

子类的对象中含有父类的成分。

image-20240305133932189

2.复合

Compositon,表现为has-a

比如,queue这个class中有个变量c,c是一个deque类型。那么queue和deque表现出来的关系就是复合。

屏幕截图 2024-03-04 163445

Adapter:已有完善、功能很强大的类,根据客户需求修改接口来实现具有一小部分功能的类(改造一下),所使用的接口都是已有的类里的。

从内存的角度看

image-20240305113521918

composition关系下的构造和析构

image-20240305113656682
构造就像搭积木,一层一层由内像外。因此在调用container的构造函数时候,第一步先调用component的构造函数。
析构就像剥洋葱,由外向内一层一层剥开。因此最后才调用component的析构函数。

image-20240305115237911

3.委托

两个类之间的关系是用指针相连。

image-20240305115454818

如图所示:String类只是一个对外的接口,具体的实现都在StringRep类中。

有三个不同的String对象同时指向"Hello",那么是共享同一份数据。

特点就是:读时共享,写时拷贝。copy on write。如果a想要改变内容,那么单独提供一份副本给a,b、c继续指向同一个"Hello"。

(11) 虚函数与多态

函数继承的是调用权,子类可以调用父类的函数。

重点在于:子类需不需要重新定义父类的函数。

image-20240305135436127

  • 非虚函数:子类不可以重写。
  • 虚函数:子类可以重写,不重写的话也有默认的定义。
  • 纯虚函数:子类一定要重写,否则编译不通过。
  • 空函数:子类不需要重写。
Template Method

image-20240305141704694

父类设计好某些功能的通用、一般性的实现,只留无法决定的函数交给子类去重写。

如图,创建一个子类的对象myDoc,调用父类的函数OnFileOpen(),在OnFileOpen函数的执行过程中,发现Serialize函数被子类重写了,因此转过去执行子类重写的该函数,最后再回到父类的OnFileOpen中执行。

image-20240305144032438

继承+复合关系

构造和析构

image-20240305145041323

image-20240305145058843

image-20240305145219065

image-20240305145245957

继承+委托关系
observer

什么情况需要用到这种设计模式?

假设我们有一份数据,但是需要用多种方式对这份数据进行查看。

image-20240305145436943

如图所示,我们只有一份数据,但是需要用多种不同的方式对数据进行查看(直观、柱状图、折线图等等)。拥有同一份数据的副本我们就可以想到委托的特点读时共享。

image-20240305145646612

image-20240305150826859

image-20240305150854932

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/431545.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Igraph入门指南 1

Igraph入门指南 一、图的结构 图是顶点和边的集合&#xff0c;而边是通过顶点来描述。顶点和边&#xff0c;要用集合的理念去操作。 1、igraph中与图结构相关的函数 .igraph(), add_edges(), add_vertices(), complementer(),compose(), connect(), contract(), delete_ed…

自我对比: 通过不一致的解决视角更好地进行反思

一、写作动机&#xff1a; LLM 在自我评价时往往过于自信或随意性较大&#xff0c;提供的反馈固执或不一致&#xff0c;从而导致反思效果不佳。为了解决这个问题&#xff0c;作者提倡 "自我对比"&#xff1a; 它可以根据要求探索不同的解决角度&#xff0c;对比差异…

并发编程并发安全性之Lock锁及原理分析

ReentrantLock 用途:锁是用来解决线程安全问题的 重入锁-> 互斥锁 满足线程的互斥性意味着同一个时刻&#xff0c;只允许一个线程进入到加锁的代码中。多线程环境下&#xff0c;满足线程的顺序访问 锁的设计猜想 一定会涉及到锁的抢占&#xff0c;需要有一个标记来实现互…

论文学习—Model-based Adversarial Meta-Reinforcement Learning

Model-based Adversarial Meta-Reinforcement Learning Abstract1. Introduction2. Related work3 Preliminaries基于模型的强化学习&#xff08;MBRL&#xff09;:区别和联系&#xff1a; 4 Model-based Adversarial Meta-Reinforcement Learning4.1 Formulation 4.2 Computin…

java实现文件上传到本地

很多时候我们都需要进行文件上传和下载的操作&#xff0c;具体怎么实现网上的代码其实也是挺多的&#xff0c;刚好我的项目中也遇到了文件上传和下载的需求&#xff0c;本篇博文具体讲解上传操作&#xff0c;下篇博文讲解下载操作。 我们具体来想一想要将一个从前端传来的文件…

【原理图PCB专题】Allegro模块化移动器件报...has the LOCKED property怎么解锁?

在模块化原理图时,PCB也需要做一个模块.mdd文件。这时需要先画好图纸然后再制作模块化文件。 修改文件时会发现模块化器件报错,无法编辑模块内部器件和走线,器件和走线都被LOCKED,如下所示报错内容: Symbol "U1" Selected Cannot edit Symbol "U1". M…

磁性机器人在医学领域取得进展

磁性医疗机器人利用磁场梯度来控制设备的运动&#xff0c;并最终以高精度进入体内的目标组织。这些磁性机器人可以采用导管和微型或纳米机器人的形式&#xff0c;并由磁导航系统操纵。磁性机器人最近取得了一些进展&#xff0c;为临床诊断和治疗用途开辟了新的可能性。在本期的…

数据结构与算法:堆排序和TOP-K问题

朋友们大家好&#xff0c;本节内容来到堆的应用&#xff1a;堆排序和topk问题 堆排序 1.堆排序的实现1.1排序 2.TOP-K问题3.向上调整建堆与向下调整建堆3.1对比两种方法的时间复杂度 我们在c语言中已经见到过几种排序&#xff0c;冒泡排序&#xff0c;快速排序&#xff08;qsor…

2024.3.5

作业1、使用select实现tcp服务器端&#xff0c;poll实现tcp客户端 服务器端&#xff1a; #include <myhead.h> #define SER_IP "192.168.199.131" //服务端IP #define SER_PORT 8888 //服务端端口号int main(int argc, const char *argv[])…

星瑞格数据库管理系统

一. 产品介绍 随着信息化的到来&#xff0c;数据安全成为保障信息化建设的一个关键问题&#xff1b;数据库作为信息化系统的基础软件其自身安全以及对数据的保障是至关重要。现阶段国内重要部门的信息系统存放着大量敏感数据&#xff0c;为了保障其数据的安全性&#xff0c;使用…

Mathcad tips_table相关

1. 可以插入表格&#xff0c;或者2. 从excel 文件导入 选择列 选择其中一行的数值

Batch Normalization和Layer Normalization和Group normalization

文章目录 前言一、Group normalization二、批量规范化(Batch Normalization)三、层规范化&#xff08;Layer Normalization&#xff09; 前言 批量规范化和层规范化在神经网络中的每个批次或每个层上进行规范化&#xff0c;而GroupNorm将特征分成多个组&#xff0c;并在每个组内…

HarmonyOS创建项目和应用—设置数据处理位置

项目和应用介绍 关于项目 项目是资源、应用的组织实体。资源包括服务器、数据库、存储&#xff0c;以及您的应用、终端用户的数据等。在您使用部分服务时&#xff0c;您是数据的控制者&#xff0c;数据将按照您设置的数据处理位置来存储在指定区域。 通常&#xff0c;您不需…

Mybatis实现分页查询数据(代码实操讲解)

在MyBatis中实现分页查询的常见方式有两种&#xff1a;使用MyBatis内置的分页插件如PageHelper&#xff0c;或者手动编写分页的SQL语句。下面我将为你提供两种方式的示例代码。 使用PageHelper分页插件 首先&#xff0c;确保你的项目中已经添加了PageHelper的依赖。在Maven项…

ZYNQ--关于一些SDK调试问题记录

Debug configuaration中没有debug applicaton 问题如下图&#xff1a; 解决方法&#xff1a; 在Target Setup中的Debug Type中选择如下即可 注意选完之后application中必须勾选运行内核&#xff0c;否则不运行main文件。

Java项目:36 springboot图书个性化推荐系统的设计与实现003

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 springboot003图书个性化推荐系统的设计与实现 管理员&#xff1a;首页、个人中心、学生管理、图书分类管理、图书信息管理、图书预约管理、退…

2195. 深海机器人问题(网络流,费用流,上下界可行流,网格图模型)

活动 - AcWing 深海资源考察探险队的潜艇将到达深海的海底进行科学考察。 潜艇内有多个深海机器人。 潜艇到达深海海底后&#xff0c;深海机器人将离开潜艇向预定目标移动。 深海机器人在移动中还必须沿途采集海底生物标本。 沿途生物标本由最先遇到它的深海机器人完成采…

vue3基础教程(2)——创建vue3+vite项目

博主个人微信小程序已经上线&#xff1a;【中二少年工具箱】。欢迎搜索试用 正文开始 专栏简介1. 前言2.node版本检测3.创建vue项目 专栏简介 本系列文章由浅入深&#xff0c;从基础知识到实战开发&#xff0c;非常适合入门同学。 零基础读者也能成功由本系列文章入门&#x…

循环队列:一道使数据结构萌新知道什么是“愁滋味“的题目

这破题目肝了我一天半才搞明白,也正是因为这道题目,我才豁然明白了李煜所说的"剪不断,理还乱...别是一般滋味在心头"到底是什么"滋味".在完全搞明白之前,真的是放有放不下,理也理不清... 但是理解之后你会发现,嘛い---,也就那么个回事嘛O(∩_∩)O 目录 1…

【DreamTalk】源码部署

安装 # 下载源码 git clone https://github.com/ali-vilab/dreamtalk cd dreamtalkconda create -n dreamtalk python3.10 conda activate dreamtalkconda install -c conda-forge yacs0.1.8 conda install -c conda-forge numpy1.21.5 conda install -c conda-forge av10.0.0…