【侯捷】C++面向对象 (上)

news2024/10/10 4:24:17

1.C++ 编程简介 & 目标

  • 培养代码正规编范
  • class 分为 带pointer 和 不带pointer的

image.png

  • 学习C++ : 语言 + 标准库

2.C vs C++

  • C语言 : (type)数据 + 函数 —create—》 数据s
  • C++ : (class ) 数据 + 成员 —create—》 对象
  • 不带指针的类 :complex 复数
  • 带指针的类 : string 字符串
  • 如果是自己写的头文件 那就必须加上防卫式的声明

image.png

  • 头文件布局:

image.png

  • 然后就是body/ 函数设计
  • 函数可以直接在body定义 (inline 函数) 或者 在外部定义
  • inline 函数 :比较快 比较好 并不是什么函数都可以是 inline 如果函数太复杂就不行, 能否inline 仍然又编译器决定。
  • private : 数据部分 写函数调用获取 prublic 俩部分可以分很多段写

3.构造函数

  • C++ 如果创建一个对象 ,自动调用的函数 就是构造函数
  • 函数名称 与 类名称一样
  • 初值列表 : 构造函数独有的 , 不适用 赋值的方式 先执行初值列表,再执行body里面的, 如果使用赋值 就会影响效率 比较差

image.png

  • 构造函数不需要写类型 不带指针的类多半不需要写虚构函数
  • 构造函数可以有很多个 overloading(重载)
  • 构造函数如果放在private 区 将无法被外界调用 但可以使用单例模式 进行设计

image.png

  • 凡是对不会改变的变量 通通加上const 变成常量成员函数

image.png

  • 如果定义是const 但是 real 和imag、函数都没加const 则会报错

image.png

传参 or 传引用?

  • 传值的话,值多大 就传多大,传的动作加上压到函数的栈里面去, 多少个byte就穿多少, 传指针 == 传地址 4byte
  • 传引用 0 byte , 比指针更好 , 相当于传指针, 快, 最好都是传引用 , 如果传过去的变量,不希望对方修改,那么就必须加上const

返回传递 return by value vs return by reference(to const)

  • 如果在可以的情况下 必须 return by reference(to const)
  • 如果不是(局部)local object 就可以传引用
  • 比如在函数中创建一个变量, 然后对这啊 v f个变量进行return by referenbce, 变量脱离函数就会销毁, 所以不能 return by referenbce

友元 friend

  • 设置friend 就可以直接获取 和public一样, 但是不写friend 获取就只能通过函数,效率会下降.

  • image.png

05 image.png

  • 首要考虑 & 然后再看 , 使用 & 会不会出错,如果会就改80

4.操作符重载

complex.h

#ifndef __MYCOMPLEX__
#define __MYCOMPLEX__

class complex; 
complex&
__doapl (complex* ths, const complex& r);
complex&
__doami (complex* ths, const complex& r);
complex&
__doaml (complex* ths, const complex& r);


class complex
{
public:
complex (double r = 0, double i = 0): re (r), im (i) { }
complex& operator += (const complex&);
complex& operator -= (const complex&);
complex& operator *= (const complex&);
complex& operator /= (const complex&);
double real () const { return re; }
double imag () const { return im; }
private:    
double re, im;

friend complex& __doapl (complex *, const complex&);
friend complex& __doami (complex *, const complex&);
friend complex& __doaml (complex *, const complex&);
};


inline complex&
__doapl (complex* ths, const complex& r)
{
    ths->re += r.re;
    ths->im += r.im;
    return *ths;
}

inline complex&
complex::operator += (const complex& r)
{
    return __doapl (this, r);
}

inline complex&
__doami (complex* ths, const complex& r)
{
    ths->re -= r.re;
    ths->im -= r.im;
    return *ths;
}

inline complex&
complex::operator -= (const complex& r)
{
    return __doami (this, r);
}

inline complex&
__doaml (complex* ths, const complex& r)
{
    double f = ths->re * r.re - ths->im * r.im;
    ths->im = ths->re * r.im + ths->im * r.re;
    ths->re = f;
    return *ths;
}

inline complex&
complex::operator *= (const complex& r)
{
    return __doaml (this, r);
}

inline double
imag (const complex& x)
{
    return x.imag ();
}

inline double
real (const complex& x)
{
    return x.real ();
}

inline complex
operator + (const complex& x, const complex& y)
{
    return complex (real (x) + real (y), imag (x) + imag (y));
}

inline complex
operator + (const complex& x, double y)
{
    return complex (real (x) + y, imag (x));
}

inline complex
operator + (double x, const complex& y)
{
    return complex (x + real (y), imag (y));
}

inline complex
operator - (const complex& x, const complex& y)
{
    return complex (real (x) - real (y), imag (x) - imag (y));
}

inline complex
operator - (const complex& x, double y)
{
    return complex (real (x) - y, imag (x)); // 被减数
}	

inline complex
operator - (double x, const complex& y)
{
    return complex (x - real (y), - imag (y));  // 减数
}

inline complex
operator + (const complex& x)  // 正值
{
    return x;
}

inline complex
operator - (const complex& x)  // 负值
{
    return complex (-real (x), -imag (x));
}


inline complex
operator * (const complex& x, const complex& y)
{
    return complex (real (x) * real (y) - imag (x) * imag (y),
        real (x) * imag (y) + imag (x) * real (y));
}

inline complex
operator * (const complex& x, double y)
{
    return complex (real (x) * y, imag (x) * y);
}

inline complex
operator * (double x, const complex& y)
{
    return complex (x * real (y), x * imag (y));
}

complex
operator / (const complex& x, double y)
{
    return complex (real (x) / y, imag (x) / y);
}


inline bool
operator == (const complex& x, const complex& y)
{
    return real (x) == real (y) && imag (x) == imag (y);
        }

        inline bool
        operator == (const complex& x, double y)
    {
        return real (x) == y && imag (x) == 0;
        }

        inline bool
        operator == (double x, const complex& y)
    {
        return x == real (y) && imag (y) == 0;
        }

        inline bool
        operator != (const complex& x, const complex& y)
    {
        return real (x) != real (y) || imag (x) != imag (y);
        }

        inline bool
        operator != (const complex& x, double y)
    {
        return real (x) != y || imag (x) != 0;
        }

        inline bool
        operator != (double x, const complex& y)
    {
        return x != real (y) || imag (y) != 0;
        }

        #include <cmath>

        inline complex
        polar (double r, double t)
    {
        return complex (r * cos (t), r * sin (t));
        }

        inline complex
        conj (const complex& x)  //鍏辫江澶嶆暟
    {
        return complex (real (x), -imag (x));
        }

        inline double
        norm (const complex& x)
    {
        return real (x) * real (x) + imag (x) * imag (x);
        }

        #endif   //__MYCOMPLEX__

5.类的区分

image.png
就是成员函数是否带指针

6.浅拷贝 & 深拷贝

在 C++ 中,浅拷贝和深拷贝是两种不同的复制对象的方法。浅拷贝是通过简单地复制原始对象的所有变量的数据来创建一个对象。这种方法适用于对象的变量没有在堆内存区域定义的情况。如果某些变量是从堆内存区域动态分配的内存,则复制的对象变量也将引用相同的内存位置。这将导致歧义和运行时错误,悬空指针。由于两个对象都将引用相同的内存位置,因此一个对象所做的更改也会反映在另一个对象上。由于我们希望创建一个对象的副本,因此浅拷贝无法实现这一目的。
image.png
深拷贝是通过复制所有变量的数据并为对象分配相同值的类似内存资源来创建一个对象。为了执行深拷贝,我们需要显式地定义复制构造函数并根据需要分配动态内存。此外,还需要在其他构造函数中为变量动态分配内存 。

inline
String::String(const String& str)  // 拷贝本身   收到的参数就是它本身 
{
   m_data = new char[ strlen(str.m_data) + 1 ];
   strcpy(m_data, str.m_data);
}

image.pngimage.png
准确性 !!
image.png

7.stack和heap

  • Stack 是存在于某作用域 (scope) 的一块内存空间 (memory space)。例如当你调用函数,函数本身即会形成一个 stack 用来放置它所接收的参数,以及返回地址。在函数本体 (function body) 内声明的任何变量,其所使用的内存块都取自上述 stack。
  • Heap,或谓 system heap,是指由操作系统提供的一块 global 内存空间,程序可动态分配 (dynamic allocated) 从某中获得若干区块 (blocks)。希望这些信息对您有所帮助!如果您有其他问题,请随时告诉我。
  • 你可以在程序的任何地方new 它, 但是你就必须要有delete 它的职责。

image.png
image.png
image.png

new & delete操作

  • newdelete 都会调用 C语言 中的 mallocfree函数

image.png
memory block
image.png

image.png

  • 保证万无一失

image.png

string类

#ifndef __MYSTRING__
#define __MYSTRING__

class String
{
public:                            
//   如果成员函数为指针  , 必须重写拷贝构造 和 拷贝复制 , 
// 不然系统会 一个字节一个字节复制  
String(const char* cstr=0);  //拷贝构造                          
String(const String& str);  //拷贝构造   拷贝本身()              
String& operator=(const String& str);  // 拷贝复制        
~String();                                    
char* get_c_str() const { return m_data; }  // 获取c风格的 str
private:
char* m_data;
};

#include <cstring>

inline
String::String(const char* cstr)
{
    if (cstr) {
        m_data = new char[strlen(cstr)+1];
        strcpy(m_data, cstr);
    }
    else {   
        m_data = new char[1];
        *m_data = '\0';
    }
}

inline
String::~String()
{
    delete[] m_data;
}

inline
String& String::operator=(const String& str)  // 
{
    if (this == &str)  // 检测自我赋值 
        return *this;

    delete[] m_data;
    m_data = new char[ strlen(str.m_data) + 1 ];
    strcpy(m_data, str.m_data);
    return *this;
}

inline
String::String(const String& str)  // 拷贝本身 
{
    m_data = new char[ strlen(str.m_data) + 1 ];
    strcpy(m_data, str.m_data);
}

#include <iostream>
using namespace std;

ostream& operator<<(ostream& os, const String& str)
{
    os << str.get_c_str();
    return os;
}
#endif

8.Static

image.png

  • static example : 利率 每个人都一样
  • static 控制static 变量
  • image.png
  • static 变量只有定义后才会出现
  • 一种设计模式 : 将构造函数 放在 private 里面

image.png

  • cout 和 模板

image.png
image.png

9.继承、符合、委托

Composition (複合)

image.png

  • 内存部分 : 内存空间

image.png

  • 调用顺序

image.png

Delegation (委托 ). Composition by reference.

  • 用指针相连 , 字符串怎么设计 , 怎么实现,都在另一个类来实现 。
  • pImpl : point to implement 可实现 引用计数 & 共享

image.png

Inheritance (繼承), 表示 is-a

image.png

  • 内存关系 :

image.png

10.虚函数与多态

  • override 重写 这个名词是针对于继承设计的
  • non-virtual 非虚函数:你不希望派生类重写 (override, 覆盖) 它。
  • virtual虚函数:你希望派生类重写 (override, 覆盖) 它,且你对它已有默认定义。
  • pure virtual 纯虚函数:你希望派生类一定要重写 (override 覆盖) 它,你对它没有默认定义

image.png
image.png

Delegation (委託) + Inheritance (繼承)

如何设计几个窗口, 内容是共享的, 一个改变 另外的类也会改变 ?

image.png

  • Observer 设计模式 :

image.png

11.委托相关设计

image.png
image.png

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【山河送书第十期】:《Python 自动化办公应用大全》参与活动,送书两本!!

【山河送书第十期】&#xff1a;《Python 自动化办公应用大全》参与活动&#xff0c;送书两本&#xff01;&#xff01; 前言一书籍亮点二作者简介三内容简介四购买链接五参与方式六往期赠书回顾 前言 在过去的 5 年里&#xff0c;Python 已经 3 次获得 TIOBE 指数年度大奖&am…

FL Studio 21.1.0官方中文破解版下载安装激活教程重磅发布含注册机

今天带来的是FL Studio 21中文版&#xff0c;内置破解补丁&#xff0c;可以完美激活程序。所有功能均可在线编辑&#xff0c;用户可直接操作。同时&#xff0c;因为FL Studio 21是最新版本&#xff0c;所以增加了新的功能。共有八种乐器和效果器插件&#xff0c;包括效果链、音…

文心一言 VS 讯飞星火 VS chatgpt (89)-- 算法导论8.3 2题

二、用go语言&#xff0c;下面的排序算法中哪些是稳定的&#xff1a;插入排序、归并排序、堆排序和快速排序?给出一个能使任何排序算法都稳定的方法。你所给出的方法带来的额外时间和空间开销是多少&#xff1f; 文心一言&#xff1a; 在Go语言中&#xff0c;以下排序算法是…

mybatis逆向工程的构建及其概念

概念 正向工程&#xff1a;先创建Java实体类&#xff0c;由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的。 逆向工程&#xff1a;先创建数据库表&#xff0c;由框架负责根据数据库表&#xff0c;反向生成如下资源&#xff1a; Java实体类 Mapper接口 Mapper配…

深度学习基础之梯度下降

1. 引言 梯度下降是一种用于最小化&#xff08;或最大化&#xff09;损失函数的优化算法。它是机器学习和深度学习中的一个关键概念&#xff0c;通常用于调整学习算法中的参数。 梯度下降背后的核心思想是迭代调整参数以最小化损失函数。它的工作原理是计算损失函数相对于每个…

解密外贸邮箱:揭秘其优势与出奇招!

外贸业务需要面对来自全球范围内的客户和供应商&#xff0c;因此&#xff0c;拥有一个高效可靠的通讯工具非常重要。在这方面&#xff0c;外贸邮箱无疑成为了外贸业务中不可或缺的一部分。那么&#xff0c;外贸邮箱有哪些优势呢&#xff1f;在这篇文章中&#xff0c;我们将会全…

【视频图像篇】FastStone Capture屏幕直尺功能设置

【视频图像篇】FastStone Capture屏幕直尺功能设置 FastStone Capture屏幕直尺功能的设置操作说明—【蘇小沐】 文章目录 【视频图像篇】FastStone Capture屏幕直尺功能设置1.实验环境 启动界面自定义工具栏1、直尺路径2、直尺方向、单位、颜色、透明度等3、直尺长度 总结 1.实…

目标检测评估指标mAP:从Precision,Recall,到AP50-95

1. TP, FP, FN, TN True Positive 满足以下三个条件被看做是TP 1. 置信度大于阈值&#xff08;类别有阈值&#xff0c;IoU判断这个bouding box是否合适也有阈值&#xff09; 2. 预测类型与标签类型相匹配&#xff08;类别预测对了&#xff09; 3. 预测的Bouding Box和Ground …

【VS Code插件开发】常见自定义命令(七)

&#x1f431; 个人主页&#xff1a;不叫猫先生&#xff0c;公众号&#xff1a;前端舵手 &#x1f64b;‍♂️ 作者简介&#xff1a;前端领域优质作者、阿里云专家博主&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4e2; 资料领取&#xff1a;前端…

java包装类简单认识泛型

1 包装类 在 Java 中&#xff0c;由于基本类型不是继承自 Object &#xff0c;为了在泛型代码中可以支持基本类型&#xff0c; Java 给每个基本类型都对应了一个包装 类型。类中比如由属性/方法 使用比较方便 1.1 基本数据类型和对应的包装类 1.2 装箱和拆箱 装包/装箱 : …

Linux使用docker安装elasticsearch-head

一、elasticsearch-head的安装启动 #下载镜像 docker pull alivv/elasticsearch-head #启动 docker run -d --name eshead -p 9100:9100 alivv/elasticsearch-head 查看日志 docker logs -f eshead 出现如下证明启动成功 浏览器访问9100端口&#xff0c;出现以下页面也说明…

java 线程安全问题 三种线程同步方案 线程通信(了解)

线程安全问题 线程安全问题指的是&#xff0c;多个线程同时操作同一个共享资源的时候&#xff0c;可能会出现业务安全问题。 下面代码演示上述问题&#xff0c;先定义一个共享的账户类&#xff1a; public class Account {private String cardId; // 卡号private double mone…

分布式版本控制工具——git

✅<1>主页&#xff1a;&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux——git ☂️<3>开发环境&#xff1a;Centos7 &#x1f4ac;<4>前言&#xff1a;git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很…

路由缓存问题 | vue-router的导航守卫

路由缓存问题 带参路由&#xff0c;当参数发生变化时&#xff0c;相同的组件实例将被复用&#xff0c;组件的生命周期钩子不会被调用&#xff0c;导致数据无法更新。 两种解决方法&#xff1a; 1. 给 RouterView绑定key值&#xff0c;即 <RouterView :key"$route.ful…

SpringBoot原理-自动配置-原理分析-源码跟踪

自动配置原理 SpringBootApplication 该注解标识在SpringBoot项目的启动类上&#xff0c;是SpringBoot中最为重要的注解&#xff0c;该注解由三个部分组成。 SpringBootConfiguration&#xff1a;该注解与Configuration注解作用一样&#xff0c;用来声明当前类为一个配置类Comp…

解决SVN文件不显示绿色小钩图标问题

问题描述&#xff1a; 今天重新安装了SVN&#xff0c;发现从中央服务器拉取文件到本地仓库后&#xff0c;对应的文件没有绿色的小钩图标&#xff0c;于是查了一下解决方案&#xff0c;在这里总结一下。 解决方案一&#xff1a; 原因&#xff1a;状态缓存设置问题造成的。 在…

2024年java面试--mysql(1)

系列文章目录 2024年java面试&#xff08;一&#xff09;–spring篇2024年java面试&#xff08;二&#xff09;–spring篇2024年java面试&#xff08;三&#xff09;–spring篇2024年java面试&#xff08;四&#xff09;–spring篇2024年java面试–集合篇2024年java面试–redi…

Java设计模式-结构性设计模式(代理设计模式)

简介 为其他对象提供⼀种代理以控制对这个对象的访问&#xff0c;属于结构型模式。客户端并不直接调⽤实际的对象&#xff0c;⽽是通过调⽤代理&#xff0c;来间接的调⽤实际的对象应用场景 各⼤数码专营店&#xff0c;代理⼚商进⾏销售对应的产品&#xff0c;代理商持有真正的…

算法训练营day46|动态规划 part08:完全背包 (LeetCode 139. 单词拆分、多重背包理论基础)

文章目录 139. 单词拆分 (求排列方法)回溯思路分析背包思路分析代码实现思考总结 多重背包理论基础 139. 单词拆分 (求排列方法) 题目链接&#x1f525;&#x1f525; 给定一个非空字符串 s 和一个包含非空单词的列表 wordDict&#xff0c;判定 s 是否可以被空格拆分为一个或多…

一文读懂LSTM及手写LSTM结构

torch.nn.LSTM是PyTorch中用于创建长短时记忆网络&#xff08;Long Short-Term Memory&#xff09;的类。LSTM是一种用于处理序列数据的循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;变体。 官方给出的LSTM API 文档 以下是 torch.nn.LSTM 的…